From fdc42afdb723d7587223b8209428c48ad1953293 Mon Sep 17 00:00:00 2001 From: JoaoBraveCoding Date: Tue, 3 Mar 2020 17:13:30 +0100 Subject: [PATCH 1/4] Added label filter for source CRD --- pkg/apis/externaldns/types.go | 3 +++ source/crd.go | 17 ++++++++++---- source/crd_test.go | 44 ++++++++++++++++++++++++++++++++++- source/store.go | 3 ++- 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 2049968831..3280a33ad7 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -47,6 +47,7 @@ type Config struct { Sources []string Namespace string AnnotationFilter string + LabelFilter string FQDNTemplate string CombineFQDNAndAnnotation bool IgnoreHostnameAnnotation bool @@ -155,6 +156,7 @@ var defaultConfig = &Config{ Sources: nil, Namespace: "", AnnotationFilter: "", + LabelFilter: "", FQDNTemplate: "", CombineFQDNAndAnnotation: false, IgnoreHostnameAnnotation: false, @@ -307,6 +309,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("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").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("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) diff --git a/source/crd.go b/source/crd.go index 26ac77e505..f563788fb4 100644 --- a/source/crd.go +++ b/source/crd.go @@ -43,6 +43,7 @@ type crdSource struct { crdResource string codec runtime.ParameterCodec annotationFilter string + labelFilter string } 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. -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{ crdResource: strings.ToLower(kind) + "s", namespace: namespace, annotationFilter: annotationFilter, + labelFilter: labelFilter, crdClient: crdClient, codec: runtime.NewParameterCodec(scheme), }, nil @@ -119,12 +121,17 @@ func (cs *crdSource) AddEventHandler(ctx context.Context, handler func()) { func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) { endpoints := []*endpoint.Endpoint{} - result, err := cs.List(ctx, &metav1.ListOptions{}) - if err != nil { - return nil, err + var result *endpoint.DNSEndpointList + var err error + + if cs.labelFilter != "" { + result, err = cs.List(&metav1.ListOptions{LabelSelector: cs.labelFilter}) + } else { + result, err = cs.List(&metav1.ListOptions{}) } - + result, err = cs.filterByAnnotations(result) + if err != nil { return nil, err } diff --git a/source/crd_test.go b/source/crd_test.go index c4f8829906..0fe94265bf 100644 --- a/source/crd_test.go +++ b/source/crd_test.go @@ -139,7 +139,9 @@ func testCRDSourceEndpoints(t *testing.T) { expectEndpoints bool expectError bool annotationFilter string + labelFilter string annotations map[string]string + labels map[string]string }{ { title: "invalid crd api version", @@ -308,6 +310,46 @@ func testCRDSourceEndpoints(t *testing.T) { expectEndpoints: true, 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) { restClient := startCRDServerToServeTargets(ti.endpoints, ti.registeredAPIVersion, ti.registeredKind, ti.registeredNamespace, "test", ti.annotations, t) @@ -317,7 +359,7 @@ func testCRDSourceEndpoints(t *testing.T) { scheme := runtime.NewScheme() 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()) if ti.expectError { diff --git a/source/store.go b/source/store.go index c6cd064a23..f4657c2958 100644 --- a/source/store.go +++ b/source/store.go @@ -42,6 +42,7 @@ var ErrSourceNotFound = errors.New("source not found") type Config struct { Namespace string AnnotationFilter string + LabelFilter string FQDNTemplate string CombineFQDNAndAnnotation bool IgnoreHostnameAnnotation bool @@ -246,7 +247,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err if err != nil { 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": apiServerURL := cfg.APIServerURL tokenPath := "" From 328465e52c2e49758e375d10d8602253d825e3a1 Mon Sep 17 00:00:00 2001 From: JoaoBraveCoding Date: Fri, 6 Mar 2020 14:44:56 +0100 Subject: [PATCH 2/4] Fixed bug with labels and added tests for source CRD --- main.go | 1 + source/crd_test.go | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 1a02976a27..a4097fba79 100644 --- a/main.go +++ b/main.go @@ -100,6 +100,7 @@ func main() { sourceCfg := &source.Config{ Namespace: cfg.Namespace, AnnotationFilter: cfg.AnnotationFilter, + LabelFilter: cfg.LabelFilter, FQDNTemplate: cfg.FQDNTemplate, CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation, IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation, diff --git a/source/crd_test.go b/source/crd_test.go index 0fe94265bf..23048cc173 100644 --- a/source/crd_test.go +++ b/source/crd_test.go @@ -57,7 +57,7 @@ func objBody(codec runtime.Encoder, obj runtime.Object) io.ReadCloser { 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) scheme := runtime.NewScheme() addKnownTypes(scheme, groupVersion) @@ -72,6 +72,7 @@ func startCRDServerToServeTargets(endpoints []*endpoint.Endpoint, apiVersion, ki Name: name, Namespace: namespace, Annotations: annotations, + Labels: labels, Generation: 1, }, Spec: endpoint.DNSEndpointSpec{ @@ -352,7 +353,7 @@ func testCRDSourceEndpoints(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) require.NoError(t, err) From 1304ef34fa1130c4e5bc1de1293ac4e82eb2d9e1 Mon Sep 17 00:00:00 2001 From: JoaoBraveCoding Date: Fri, 6 Mar 2020 15:46:32 +0100 Subject: [PATCH 3/4] Fixed formating --- pkg/apis/externaldns/types.go | 2 +- source/crd.go | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 3280a33ad7..3e9537d79d 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -309,7 +309,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("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").Default(defaultConfig.LabelFilter).StringVar(&cfg.LabelFilter) + 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("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) diff --git a/source/crd.go b/source/crd.go index f563788fb4..a897d45aa1 100644 --- a/source/crd.go +++ b/source/crd.go @@ -43,7 +43,7 @@ type crdSource struct { crdResource string codec runtime.ParameterCodec annotationFilter string - labelFilter string + labelFilter string } func addKnownTypes(scheme *runtime.Scheme, groupVersion schema.GroupVersion) error { @@ -108,7 +108,7 @@ func NewCRDSource(crdClient rest.Interface, namespace, kind string, annotationFi crdResource: strings.ToLower(kind) + "s", namespace: namespace, annotationFilter: annotationFilter, - labelFilter: labelFilter, + labelFilter: labelFilter, crdClient: crdClient, codec: runtime.NewParameterCodec(scheme), }, nil @@ -121,15 +121,20 @@ func (cs *crdSource) AddEventHandler(ctx context.Context, handler func()) { func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) { endpoints := []*endpoint.Endpoint{} - var result *endpoint.DNSEndpointList - var err error - + var ( + result *endpoint.DNSEndpointList + err error + ) + if cs.labelFilter != "" { - result, err = cs.List(&metav1.ListOptions{LabelSelector: cs.labelFilter}) + result, err = cs.List(ctx, &metav1.ListOptions{LabelSelector: cs.labelFilter}) } else { - result, err = cs.List(&metav1.ListOptions{}) + result, err = cs.List(ctx, &metav1.ListOptions{}) + } + if err != nil { + return nil, err } - + result, err = cs.filterByAnnotations(result) if err != nil { From 56e62d04b09aaf856dc647128660402b3bc5dd97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Mar=C3=A7al?= Date: Thu, 17 Sep 2020 09:25:50 +0200 Subject: [PATCH 4/4] Update source/crd_test.go Co-authored-by: Vinny Sabatini --- source/crd_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/crd_test.go b/source/crd_test.go index 23048cc173..c669b50803 100644 --- a/source/crd_test.go +++ b/source/crd_test.go @@ -72,7 +72,7 @@ func startCRDServerToServeTargets(endpoints []*endpoint.Endpoint, apiVersion, ki Name: name, Namespace: namespace, Annotations: annotations, - Labels: labels, + Labels: labels, Generation: 1, }, Spec: endpoint.DNSEndpointSpec{