-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(source/pod): add support for fqdn templating #5512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
fc790f3
b93ddf8
c4a7d10
77f1127
f036698
66c92f9
343f1aa
500db5a
c8a549c
626933e
f4e5410
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,9 @@ package source | |
|
||
import ( | ||
"context" | ||
"fmt" | ||
"maps" | ||
"text/template" | ||
|
||
log "github.com/sirupsen/logrus" | ||
corev1 "k8s.io/api/core/v1" | ||
|
@@ -27,14 +30,19 @@ import ( | |
"k8s.io/client-go/kubernetes" | ||
"k8s.io/client-go/tools/cache" | ||
|
||
"sigs.k8s.io/external-dns/source/fqdn" | ||
|
||
"sigs.k8s.io/external-dns/endpoint" | ||
"sigs.k8s.io/external-dns/source/annotations" | ||
"sigs.k8s.io/external-dns/source/informers" | ||
) | ||
|
||
type podSource struct { | ||
client kubernetes.Interface | ||
namespace string | ||
client kubernetes.Interface | ||
namespace string | ||
fqdnTemplate *template.Template | ||
combineFQDNAnnotation bool | ||
|
||
podInformer coreinformers.PodInformer | ||
nodeInformer coreinformers.NodeInformer | ||
compatibility string | ||
|
@@ -43,18 +51,27 @@ type podSource struct { | |
} | ||
|
||
// NewPodSource creates a new podSource with the given config. | ||
func NewPodSource(ctx context.Context, kubeClient kubernetes.Interface, namespace string, compatibility string, ignoreNonHostNetworkPods bool, podSourceDomain string) (Source, error) { | ||
func NewPodSource( | ||
ctx context.Context, | ||
kubeClient kubernetes.Interface, | ||
namespace string, | ||
compatibility string, | ||
ignoreNonHostNetworkPods bool, | ||
podSourceDomain string, | ||
fqdnTemplate string, | ||
combineFqdnAnnotation bool, | ||
) (Source, error) { | ||
informerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, 0, kubeinformers.WithNamespace(namespace)) | ||
podInformer := informerFactory.Core().V1().Pods() | ||
nodeInformer := informerFactory.Core().V1().Nodes() | ||
|
||
podInformer.Informer().AddEventHandler( | ||
_, _ = podInformer.Informer().AddEventHandler( | ||
cache.ResourceEventHandlerFuncs{ | ||
AddFunc: func(obj interface{}) { | ||
}, | ||
}, | ||
) | ||
nodeInformer.Informer().AddEventHandler( | ||
_, _ = nodeInformer.Informer().AddEventHandler( | ||
cache.ResourceEventHandlerFuncs{ | ||
AddFunc: func(obj interface{}) { | ||
}, | ||
|
@@ -68,6 +85,11 @@ func NewPodSource(ctx context.Context, kubeClient kubernetes.Interface, namespac | |
return nil, err | ||
} | ||
|
||
tmpl, err := fqdn.ParseTemplate(fqdnTemplate) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &podSource{ | ||
client: kubeClient, | ||
podInformer: podInformer, | ||
|
@@ -76,22 +98,35 @@ func NewPodSource(ctx context.Context, kubeClient kubernetes.Interface, namespac | |
compatibility: compatibility, | ||
ignoreNonHostNetworkPods: ignoreNonHostNetworkPods, | ||
podSourceDomain: podSourceDomain, | ||
fqdnTemplate: tmpl, | ||
combineFQDNAnnotation: combineFqdnAnnotation, | ||
}, nil | ||
} | ||
|
||
func (*podSource) AddEventHandler(ctx context.Context, handler func()) { | ||
func (*podSource) AddEventHandler(_ context.Context, _ func()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, do you know why this function does nothing? (Other sources often add the handler to informers) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. We need to fix that as well. Related PR #5274 We need to review and fix all the handlers. It's a useful feature. I'm not too sure how it differ from adding handlers in constructur, that the only gotcha |
||
} | ||
|
||
func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) { | ||
func (ps *podSource) Endpoints(_ context.Context) ([]*endpoint.Endpoint, error) { | ||
pods, err := ps.podInformer.Lister().Pods(ps.namespace).List(labels.Everything()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
endpointMap := make(map[endpoint.EndpointKey][]string) | ||
for _, pod := range pods { | ||
ps.addPodEndpointsToEndpointMap(endpointMap, pod) | ||
if ps.fqdnTemplate == nil || ps.combineFQDNAnnotation { | ||
ps.addPodEndpointsToEndpointMap(endpointMap, pod) | ||
} | ||
|
||
if ps.fqdnTemplate != nil { | ||
fqdnHosts, err := ps.hostsFromTemplate(pod) | ||
if err != nil { | ||
return nil, err | ||
} | ||
maps.Copy(endpointMap, fqdnHosts) | ||
} | ||
} | ||
|
||
var endpoints []*endpoint.Endpoint | ||
for key, targets := range endpointMap { | ||
endpoints = append(endpoints, endpoint.NewEndpoint(key.DNSName, key.RecordType, targets...)) | ||
|
@@ -180,6 +215,30 @@ func (ps *podSource) addPodNodeEndpointsToEndpointMap(endpointMap map[endpoint.E | |
} | ||
} | ||
|
||
func (ps *podSource) hostsFromTemplate(pod *corev1.Pod) (map[endpoint.EndpointKey][]string, error) { | ||
hosts, err := fqdn.ExecTemplate(ps.fqdnTemplate, pod) | ||
if err != nil { | ||
return nil, fmt.Errorf("skipping generating endpoints from template for pod %s: %w", pod.Name, err) | ||
} | ||
|
||
result := make(map[endpoint.EndpointKey][]string) | ||
for _, target := range hosts { | ||
for _, address := range pod.Status.PodIPs { | ||
if address.IP == "" { | ||
log.Debugf("skipping pod %q. PodIP is empty with phase %q", pod.Name, pod.Status.Phase) | ||
continue | ||
} | ||
key := endpoint.EndpointKey{ | ||
DNSName: target, | ||
RecordType: suitableType(address.IP), | ||
} | ||
result[key] = append(result[key], address.IP) | ||
} | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func addTargetsToEndpointMap(endpointMap map[endpoint.EndpointKey][]string, targets []string, domainList ...string) { | ||
for _, domain := range domainList { | ||
for _, target := range targets { | ||
|
Uh oh!
There was an error while loading. Please reload this page.