mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 01:26:59 +02:00
Merge pull request #2220 from ericrrath/crd-source-event-handler
CRD source: add event-handler support
This commit is contained in:
commit
e6ec8ea329
1
main.go
1
main.go
@ -140,6 +140,7 @@ func main() {
|
|||||||
RequestTimeout: cfg.RequestTimeout,
|
RequestTimeout: cfg.RequestTimeout,
|
||||||
DefaultTargets: cfg.DefaultTargets,
|
DefaultTargets: cfg.DefaultTargets,
|
||||||
OCPRouterName: cfg.OCPRouterName,
|
OCPRouterName: cfg.OCPRouterName,
|
||||||
|
UpdateEvents: cfg.UpdateEvents,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup all the selected sources by names and pass them the desired configuration.
|
// Lookup all the selected sources by names and pass them the desired configuration.
|
||||||
|
@ -22,6 +22,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
@ -44,6 +48,7 @@ type crdSource struct {
|
|||||||
codec runtime.ParameterCodec
|
codec runtime.ParameterCodec
|
||||||
annotationFilter string
|
annotationFilter string
|
||||||
labelSelector labels.Selector
|
labelSelector labels.Selector
|
||||||
|
informer *cache.SharedInformer
|
||||||
}
|
}
|
||||||
|
|
||||||
func addKnownTypes(scheme *runtime.Scheme, groupVersion schema.GroupVersion) error {
|
func addKnownTypes(scheme *runtime.Scheme, groupVersion schema.GroupVersion) error {
|
||||||
@ -103,18 +108,55 @@ func NewCRDClientForAPIVersionKind(client kubernetes.Interface, kubeConfig, apiS
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewCRDSource creates a new crdSource with the given config.
|
// NewCRDSource creates a new crdSource with the given config.
|
||||||
func NewCRDSource(crdClient rest.Interface, namespace, kind string, annotationFilter string, labelSelector labels.Selector, scheme *runtime.Scheme) (Source, error) {
|
func NewCRDSource(crdClient rest.Interface, namespace, kind string, annotationFilter string, labelSelector labels.Selector, scheme *runtime.Scheme, startInformer bool) (Source, error) {
|
||||||
return &crdSource{
|
sourceCrd := crdSource{
|
||||||
crdResource: strings.ToLower(kind) + "s",
|
crdResource: strings.ToLower(kind) + "s",
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
annotationFilter: annotationFilter,
|
annotationFilter: annotationFilter,
|
||||||
labelSelector: labelSelector,
|
labelSelector: labelSelector,
|
||||||
crdClient: crdClient,
|
crdClient: crdClient,
|
||||||
codec: runtime.NewParameterCodec(scheme),
|
codec: runtime.NewParameterCodec(scheme),
|
||||||
}, nil
|
}
|
||||||
|
if startInformer {
|
||||||
|
// external-dns already runs its sync-handler periodically (controlled by `--interval` flag) to ensure any
|
||||||
|
// missed or dropped events are handled. specify a resync period 0 to avoid unnecessary sync handler invocations.
|
||||||
|
informer := cache.NewSharedInformer(
|
||||||
|
&cache.ListWatch{
|
||||||
|
ListFunc: func(lo metav1.ListOptions) (result runtime.Object, err error) {
|
||||||
|
return sourceCrd.List(context.TODO(), &lo)
|
||||||
|
},
|
||||||
|
WatchFunc: func(lo metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
return sourceCrd.watch(context.TODO(), &lo)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&endpoint.DNSEndpoint{},
|
||||||
|
0)
|
||||||
|
sourceCrd.informer = &informer
|
||||||
|
go informer.Run(wait.NeverStop)
|
||||||
|
}
|
||||||
|
return &sourceCrd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *crdSource) AddEventHandler(ctx context.Context, handler func()) {
|
func (cs *crdSource) AddEventHandler(ctx context.Context, handler func()) {
|
||||||
|
if cs.informer != nil {
|
||||||
|
log.Debug("Adding event handler for CRD")
|
||||||
|
// Right now there is no way to remove event handler from informer, see:
|
||||||
|
// https://github.com/kubernetes/kubernetes/issues/79610
|
||||||
|
informer := *cs.informer
|
||||||
|
informer.AddEventHandler(
|
||||||
|
cache.ResourceEventHandlerFuncs{
|
||||||
|
AddFunc: func(obj interface{}) {
|
||||||
|
handler()
|
||||||
|
},
|
||||||
|
UpdateFunc: func(old interface{}, new interface{}) {
|
||||||
|
handler()
|
||||||
|
},
|
||||||
|
DeleteFunc: func(obj interface{}) {
|
||||||
|
handler()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Endpoints returns endpoint objects.
|
// Endpoints returns endpoint objects.
|
||||||
@ -189,6 +231,15 @@ func (cs *crdSource) setResourceLabel(crd *endpoint.DNSEndpoint, endpoints []*en
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *crdSource) watch(ctx context.Context, opts *metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
opts.Watch = true
|
||||||
|
return cs.crdClient.Get().
|
||||||
|
Namespace(cs.namespace).
|
||||||
|
Resource(cs.crdResource).
|
||||||
|
VersionedParams(opts, cs.codec).
|
||||||
|
Watch(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *crdSource) List(ctx context.Context, opts *metav1.ListOptions) (result *endpoint.DNSEndpointList, err error) {
|
func (cs *crdSource) List(ctx context.Context, opts *metav1.ListOptions) (result *endpoint.DNSEndpointList, err error) {
|
||||||
result = &endpoint.DNSEndpointList{}
|
result = &endpoint.DNSEndpointList{}
|
||||||
err = cs.crdClient.Get().
|
err = cs.crdClient.Get().
|
||||||
|
@ -398,7 +398,12 @@ func testCRDSourceEndpoints(t *testing.T) {
|
|||||||
labelSelector, err := labels.Parse(ti.labelFilter)
|
labelSelector, err := labels.Parse(ti.labelFilter)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cs, err := NewCRDSource(restClient, ti.namespace, ti.kind, ti.annotationFilter, labelSelector, scheme)
|
// At present, client-go's fake.RESTClient (used by crd_test.go) is known to cause race conditions when used
|
||||||
|
// with informers: https://github.com/kubernetes/kubernetes/issues/95372
|
||||||
|
// So don't start the informer during testing.
|
||||||
|
startInformer := false
|
||||||
|
|
||||||
|
cs, err := NewCRDSource(restClient, ti.namespace, ti.kind, ti.annotationFilter, labelSelector, scheme, startInformer)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
receivedEndpoints, err := cs.Endpoints(context.Background())
|
receivedEndpoints, err := cs.Endpoints(context.Background())
|
||||||
|
@ -72,6 +72,7 @@ type Config struct {
|
|||||||
RequestTimeout time.Duration
|
RequestTimeout time.Duration
|
||||||
DefaultTargets []string
|
DefaultTargets []string
|
||||||
OCPRouterName string
|
OCPRouterName string
|
||||||
|
UpdateEvents bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientGenerator provides clients
|
// ClientGenerator provides clients
|
||||||
@ -308,7 +309,7 @@ func BuildWithConfig(ctx context.Context, source string, p ClientGenerator, cfg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewCRDSource(crdClient, cfg.Namespace, cfg.CRDSourceKind, cfg.AnnotationFilter, cfg.LabelFilter, scheme)
|
return NewCRDSource(crdClient, cfg.Namespace, cfg.CRDSourceKind, cfg.AnnotationFilter, cfg.LabelFilter, scheme, cfg.UpdateEvents)
|
||||||
case "skipper-routegroup":
|
case "skipper-routegroup":
|
||||||
apiServerURL := cfg.APIServerURL
|
apiServerURL := cfg.APIServerURL
|
||||||
tokenPath := ""
|
tokenPath := ""
|
||||||
|
Loading…
Reference in New Issue
Block a user