mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-07 01:56:57 +02:00
Added labelFilter for source CRD (#1461)
* Added label filter for source CRD * Fixed bug with labels and added tests for source CRD * Fixed formating * Update source/crd_test.go Co-authored-by: Vinny Sabatini <vincent.sabatini@gmail.com> Co-authored-by: Vinny Sabatini <vincent.sabatini@gmail.com>
This commit is contained in:
parent
32fedeaf07
commit
79ea64884b
1
main.go
1
main.go
@ -100,6 +100,7 @@ func main() {
|
|||||||
sourceCfg := &source.Config{
|
sourceCfg := &source.Config{
|
||||||
Namespace: cfg.Namespace,
|
Namespace: cfg.Namespace,
|
||||||
AnnotationFilter: cfg.AnnotationFilter,
|
AnnotationFilter: cfg.AnnotationFilter,
|
||||||
|
LabelFilter: cfg.LabelFilter,
|
||||||
FQDNTemplate: cfg.FQDNTemplate,
|
FQDNTemplate: cfg.FQDNTemplate,
|
||||||
CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation,
|
CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation,
|
||||||
IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation,
|
IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation,
|
||||||
|
@ -47,6 +47,7 @@ type Config struct {
|
|||||||
Sources []string
|
Sources []string
|
||||||
Namespace string
|
Namespace string
|
||||||
AnnotationFilter string
|
AnnotationFilter string
|
||||||
|
LabelFilter string
|
||||||
FQDNTemplate string
|
FQDNTemplate string
|
||||||
CombineFQDNAndAnnotation bool
|
CombineFQDNAndAnnotation bool
|
||||||
IgnoreHostnameAnnotation bool
|
IgnoreHostnameAnnotation bool
|
||||||
@ -157,6 +158,7 @@ var defaultConfig = &Config{
|
|||||||
Sources: nil,
|
Sources: nil,
|
||||||
Namespace: "",
|
Namespace: "",
|
||||||
AnnotationFilter: "",
|
AnnotationFilter: "",
|
||||||
|
LabelFilter: "",
|
||||||
FQDNTemplate: "",
|
FQDNTemplate: "",
|
||||||
CombineFQDNAndAnnotation: false,
|
CombineFQDNAndAnnotation: false,
|
||||||
IgnoreHostnameAnnotation: false,
|
IgnoreHostnameAnnotation: false,
|
||||||
@ -310,6 +312,7 @@ func (cfg *Config) ParseFlags(args []string) error {
|
|||||||
|
|
||||||
app.Flag("namespace", "Limit sources of endpoints to a specific namespace (default: all namespaces)").Default(defaultConfig.Namespace).StringVar(&cfg.Namespace)
|
app.Flag("namespace", "Limit sources of endpoints to a specific namespace (default: all namespaces)").Default(defaultConfig.Namespace).StringVar(&cfg.Namespace)
|
||||||
app.Flag("annotation-filter", "Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter)
|
app.Flag("annotation-filter", "Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter)
|
||||||
|
app.Flag("label-filter", "Filter sources managed by external-dns via label selector when listing all resources; currently only supported by source CRD").Default(defaultConfig.LabelFilter).StringVar(&cfg.LabelFilter)
|
||||||
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN.").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
|
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN.").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
|
||||||
app.Flag("combine-fqdn-annotation", "Combine FQDN template and Annotations instead of overwriting").BoolVar(&cfg.CombineFQDNAndAnnotation)
|
app.Flag("combine-fqdn-annotation", "Combine FQDN template and Annotations instead of overwriting").BoolVar(&cfg.CombineFQDNAndAnnotation)
|
||||||
app.Flag("ignore-hostname-annotation", "Ignore hostname annotation when generating DNS names, valid only when using fqdn-template is set (optional, default: false)").BoolVar(&cfg.IgnoreHostnameAnnotation)
|
app.Flag("ignore-hostname-annotation", "Ignore hostname annotation when generating DNS names, valid only when using fqdn-template is set (optional, default: false)").BoolVar(&cfg.IgnoreHostnameAnnotation)
|
||||||
|
@ -43,6 +43,7 @@ type crdSource struct {
|
|||||||
crdResource string
|
crdResource string
|
||||||
codec runtime.ParameterCodec
|
codec runtime.ParameterCodec
|
||||||
annotationFilter string
|
annotationFilter string
|
||||||
|
labelFilter string
|
||||||
}
|
}
|
||||||
|
|
||||||
func addKnownTypes(scheme *runtime.Scheme, groupVersion schema.GroupVersion) error {
|
func addKnownTypes(scheme *runtime.Scheme, groupVersion schema.GroupVersion) error {
|
||||||
@ -102,11 +103,12 @@ 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, scheme *runtime.Scheme) (Source, error) {
|
func NewCRDSource(crdClient rest.Interface, namespace, kind string, annotationFilter string, labelFilter string, scheme *runtime.Scheme) (Source, error) {
|
||||||
return &crdSource{
|
return &crdSource{
|
||||||
crdResource: strings.ToLower(kind) + "s",
|
crdResource: strings.ToLower(kind) + "s",
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
annotationFilter: annotationFilter,
|
annotationFilter: annotationFilter,
|
||||||
|
labelFilter: labelFilter,
|
||||||
crdClient: crdClient,
|
crdClient: crdClient,
|
||||||
codec: runtime.NewParameterCodec(scheme),
|
codec: runtime.NewParameterCodec(scheme),
|
||||||
}, nil
|
}, nil
|
||||||
@ -119,12 +121,22 @@ func (cs *crdSource) AddEventHandler(ctx context.Context, handler func()) {
|
|||||||
func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||||
endpoints := []*endpoint.Endpoint{}
|
endpoints := []*endpoint.Endpoint{}
|
||||||
|
|
||||||
result, err := cs.List(ctx, &metav1.ListOptions{})
|
var (
|
||||||
|
result *endpoint.DNSEndpointList
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if cs.labelFilter != "" {
|
||||||
|
result, err = cs.List(ctx, &metav1.ListOptions{LabelSelector: cs.labelFilter})
|
||||||
|
} else {
|
||||||
|
result, err = cs.List(ctx, &metav1.ListOptions{})
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err = cs.filterByAnnotations(result)
|
result, err = cs.filterByAnnotations(result)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ func objBody(codec runtime.Encoder, obj runtime.Object) io.ReadCloser {
|
|||||||
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
|
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func startCRDServerToServeTargets(endpoints []*endpoint.Endpoint, apiVersion, kind, namespace, name string, annotations map[string]string, t *testing.T) rest.Interface {
|
func startCRDServerToServeTargets(endpoints []*endpoint.Endpoint, apiVersion, kind, namespace, name string, annotations map[string]string, labels map[string]string, t *testing.T) rest.Interface {
|
||||||
groupVersion, _ := schema.ParseGroupVersion(apiVersion)
|
groupVersion, _ := schema.ParseGroupVersion(apiVersion)
|
||||||
scheme := runtime.NewScheme()
|
scheme := runtime.NewScheme()
|
||||||
addKnownTypes(scheme, groupVersion)
|
addKnownTypes(scheme, groupVersion)
|
||||||
@ -72,6 +72,7 @@ func startCRDServerToServeTargets(endpoints []*endpoint.Endpoint, apiVersion, ki
|
|||||||
Name: name,
|
Name: name,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
|
Labels: labels,
|
||||||
Generation: 1,
|
Generation: 1,
|
||||||
},
|
},
|
||||||
Spec: endpoint.DNSEndpointSpec{
|
Spec: endpoint.DNSEndpointSpec{
|
||||||
@ -139,7 +140,9 @@ func testCRDSourceEndpoints(t *testing.T) {
|
|||||||
expectEndpoints bool
|
expectEndpoints bool
|
||||||
expectError bool
|
expectError bool
|
||||||
annotationFilter string
|
annotationFilter string
|
||||||
|
labelFilter string
|
||||||
annotations map[string]string
|
annotations map[string]string
|
||||||
|
labels map[string]string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
title: "invalid crd api version",
|
title: "invalid crd api version",
|
||||||
@ -308,16 +311,56 @@ func testCRDSourceEndpoints(t *testing.T) {
|
|||||||
expectEndpoints: true,
|
expectEndpoints: true,
|
||||||
expectError: false,
|
expectError: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "valid crd gvk with label and non matching label filter",
|
||||||
|
registeredAPIVersion: "test.k8s.io/v1alpha1",
|
||||||
|
apiVersion: "test.k8s.io/v1alpha1",
|
||||||
|
registeredKind: "DNSEndpoint",
|
||||||
|
kind: "DNSEndpoint",
|
||||||
|
namespace: "foo",
|
||||||
|
registeredNamespace: "foo",
|
||||||
|
labels: map[string]string{"test": "that"},
|
||||||
|
labelFilter: "test=filter_something_else",
|
||||||
|
endpoints: []*endpoint.Endpoint{
|
||||||
|
{DNSName: "abc.example.org",
|
||||||
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
|
RecordType: endpoint.RecordTypeA,
|
||||||
|
RecordTTL: 180,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectEndpoints: false,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "valid crd gvk with label and matching label filter",
|
||||||
|
registeredAPIVersion: "test.k8s.io/v1alpha1",
|
||||||
|
apiVersion: "test.k8s.io/v1alpha1",
|
||||||
|
registeredKind: "DNSEndpoint",
|
||||||
|
kind: "DNSEndpoint",
|
||||||
|
namespace: "foo",
|
||||||
|
registeredNamespace: "foo",
|
||||||
|
labels: map[string]string{"test": "that"},
|
||||||
|
labelFilter: "test=that",
|
||||||
|
endpoints: []*endpoint.Endpoint{
|
||||||
|
{DNSName: "abc.example.org",
|
||||||
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
|
RecordType: endpoint.RecordTypeA,
|
||||||
|
RecordTTL: 180,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectEndpoints: true,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ti.title, func(t *testing.T) {
|
t.Run(ti.title, func(t *testing.T) {
|
||||||
restClient := startCRDServerToServeTargets(ti.endpoints, ti.registeredAPIVersion, ti.registeredKind, ti.registeredNamespace, "test", ti.annotations, t)
|
restClient := startCRDServerToServeTargets(ti.endpoints, ti.registeredAPIVersion, ti.registeredKind, ti.registeredNamespace, "test", ti.annotations, ti.labels, t)
|
||||||
groupVersion, err := schema.ParseGroupVersion(ti.apiVersion)
|
groupVersion, err := schema.ParseGroupVersion(ti.apiVersion)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
scheme := runtime.NewScheme()
|
scheme := runtime.NewScheme()
|
||||||
addKnownTypes(scheme, groupVersion)
|
addKnownTypes(scheme, groupVersion)
|
||||||
|
|
||||||
cs, _ := NewCRDSource(restClient, ti.namespace, ti.kind, ti.annotationFilter, scheme)
|
cs, _ := NewCRDSource(restClient, ti.namespace, ti.kind, ti.annotationFilter, ti.labelFilter, scheme)
|
||||||
|
|
||||||
receivedEndpoints, err := cs.Endpoints(context.Background())
|
receivedEndpoints, err := cs.Endpoints(context.Background())
|
||||||
if ti.expectError {
|
if ti.expectError {
|
||||||
|
@ -42,6 +42,7 @@ var ErrSourceNotFound = errors.New("source not found")
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
AnnotationFilter string
|
AnnotationFilter string
|
||||||
|
LabelFilter string
|
||||||
FQDNTemplate string
|
FQDNTemplate string
|
||||||
CombineFQDNAndAnnotation bool
|
CombineFQDNAndAnnotation bool
|
||||||
IgnoreHostnameAnnotation bool
|
IgnoreHostnameAnnotation bool
|
||||||
@ -247,7 +248,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewCRDSource(crdClient, cfg.Namespace, cfg.CRDSourceKind, cfg.AnnotationFilter, scheme)
|
return NewCRDSource(crdClient, cfg.Namespace, cfg.CRDSourceKind, cfg.AnnotationFilter, cfg.LabelFilter, scheme)
|
||||||
case "skipper-routegroup":
|
case "skipper-routegroup":
|
||||||
apiServerURL := cfg.APIServerURL
|
apiServerURL := cfg.APIServerURL
|
||||||
tokenPath := ""
|
tokenPath := ""
|
||||||
|
Loading…
Reference in New Issue
Block a user