From e6749c8d3d9026bb13066c760bbe5c5fbeff027c Mon Sep 17 00:00:00 2001 From: Martin Linkhorst Date: Tue, 14 Mar 2017 10:55:12 +0100 Subject: [PATCH] feat: allow to register and lookup sources by name (#84) --- main.go | 7 ++- pkg/apis/externaldns/types.go | 2 + source/store.go | 38 +++++++++++++++ source/store_test.go | 87 +++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 source/store.go create mode 100644 source/store_test.go diff --git a/main.go b/main.go index 95329d63f..c2fe84ce7 100644 --- a/main.go +++ b/main.go @@ -74,7 +74,10 @@ func main() { log.Fatal(err) } - source := source.NewServiceSource(client, cfg.Namespace) + source.Register("service", source.NewServiceSource(client, cfg.Namespace)) + source.Register("ingress", source.NewIngressSource(client, cfg.Namespace)) + + sources := source.NewMultiSource(source.LookupMultiple(cfg.Sources...)...) dnsProvider, err := dnsprovider.NewGoogleProvider(cfg.GoogleProject, cfg.DryRun) if err != nil { @@ -83,7 +86,7 @@ func main() { ctrl := controller.Controller{ Zone: cfg.GoogleZone, - Source: source, + Source: sources, DNSProvider: dnsProvider, } diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 97abf3db9..f30eb3ba3 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -32,6 +32,7 @@ type Config struct { InCluster bool KubeConfig string Namespace string + Sources []string GoogleProject string GoogleZone string HealthPort string @@ -53,6 +54,7 @@ func (cfg *Config) ParseFlags(args []string) error { flags.BoolVar(&cfg.InCluster, "in-cluster", false, "whether to use in-cluster config") flags.StringVar(&cfg.KubeConfig, "kubeconfig", "", "path to a local kubeconfig file") flags.StringVar(&cfg.Namespace, "namespace", v1.NamespaceAll, "the namespace to look for endpoints; all namespaces by default") + flags.StringArrayVar(&cfg.Sources, "source", nil, "the sources to gather endpoints from") flags.StringVar(&cfg.GoogleProject, "google-project", "", "gcloud project to target") flags.StringVar(&cfg.GoogleZone, "google-zone", "", "gcloud dns hosted zone to target") flags.StringVar(&cfg.HealthPort, "health-port", defaultHealthPort, "health port to listen on") diff --git a/source/store.go b/source/store.go new file mode 100644 index 000000000..84fcd1701 --- /dev/null +++ b/source/store.go @@ -0,0 +1,38 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package source + +var store = map[string]Source{} + +// Register registers a Source under a given name. +func Register(name string, source Source) { + store[name] = source +} + +// Lookup returns a Source by the given name. +func Lookup(name string) Source { + return store[name] +} + +// LookupMultiple returns multiple Sources given multiple names. +func LookupMultiple(names ...string) (sources []Source) { + for _, name := range names { + sources = append(sources, Lookup(name)) + } + + return sources +} diff --git a/source/store_test.go b/source/store_test.go new file mode 100644 index 000000000..8b688f891 --- /dev/null +++ b/source/store_test.go @@ -0,0 +1,87 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package source + +import "testing" + +func TestStore(t *testing.T) { + t.Run("RegisterAndLookup", testRegisterAndLookup) + t.Run("LookupMultiple", testLookupMultiple) +} + +// testRegisterAndLookup tests that a Source can be registered and looked up by name. +func testRegisterAndLookup(t *testing.T) { + for _, tc := range []struct { + title string + givenAndExpected map[string]Source + }{ + { + "registered source is found by name", + map[string]Source{ + "foo": NewMockSource(nil), + }, + }, + } { + t.Run(tc.title, func(t *testing.T) { + for k, v := range tc.givenAndExpected { + Register(k, v) + } + + for k, v := range tc.givenAndExpected { + if Lookup(k) != v { + t.Errorf("expected %#v, got %#v", v, Lookup(k)) + } + } + }) + } +} + +// testLookupMultiple tests that Sources can be looked up by providing multiple names. +func testLookupMultiple(t *testing.T) { + for _, tc := range []struct { + title string + givenAndExpected map[string]Source + }{ + { + "multiple registered sources are found by names", + map[string]Source{ + "foo": NewMockSource(nil), + "bar": NewMockSource(nil), + }, + }, + } { + t.Run(tc.title, func(t *testing.T) { + for k, v := range tc.givenAndExpected { + Register(k, v) + } + + names, sources := []string{}, []Source{} + for k, v := range tc.givenAndExpected { + names = append(names, k) + sources = append(sources, v) + } + + lookup := LookupMultiple(names...) + + for i := range names { + if lookup[i] != sources[i] { + t.Errorf("expected %#v, got %#v", sources[i], lookup[i]) + } + } + }) + } +}