Skip to content

Commit

Permalink
Adds stubDomains and upstreamNameservers to the DNS ConfigMap
Browse files Browse the repository at this point in the history
  • Loading branch information
bowei committed Feb 17, 2017
1 parent c1b986c commit 9cd64b6
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 46 deletions.
53 changes: 52 additions & 1 deletion pkg/dns/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ limitations under the License.
package config

import (
"fmt"

types "k8s.io/client-go/pkg/apis/meta/v1"
"k8s.io/client-go/pkg/util/validation"
fed "k8s.io/dns/pkg/dns/federation"
)

Expand All @@ -35,6 +38,15 @@ type Config struct {
// Map of federation names that the cluster in which this kube-dns
// is running belongs to, to the corresponding domain names.
Federations map[string]string `json:"federations"`

// Map of stub domain to nameserver IP. The key is the domain name suffix,
// e.g. "acme.local". Key cannot be equal to the cluster domain. Value is
// the IP of the nameserver to send DNS request for the given subdomain.
StubDomains map[string][]string `json:"stubDomains"`

// List of upstream nameservers to use. Overrides nameservers inherited
// from the node.
UpstreamNameservers []string `json:"upstreamNameservers"`
}

func NewDefaultConfig() *Config {
Expand All @@ -43,12 +55,20 @@ func NewDefaultConfig() *Config {
}
}

// IsValid returns whether or not the configuration is valid.
// Validate returns whether or not the configuration is valid.
func (config *Config) Validate() error {
if err := config.validateFederations(); err != nil {
return err
}

if err := config.validateStubDomains(); err != nil {
return err
}

if err := config.validateUpstreamNameserver(); err != nil {
return err
}

return nil
}

Expand All @@ -63,3 +83,34 @@ func (config *Config) validateFederations() error {
}
return nil
}

func (config *Config) validateStubDomains() error {
for domain, nsList := range config.StubDomains {
if len(validation.IsDNS1123Subdomain(domain)) != 0 {
return fmt.Errorf("Invalid domain name: %q", domain)
}

for _, ns := range nsList {
if len(validation.IsValidIP(ns)) > 0 && len(validation.IsDNS1123Subdomain(ns)) > 0 {
return fmt.Errorf("Invalid nameserver: %q", ns)
}
}
}

return nil
}

func (config *Config) validateUpstreamNameserver() error {

if len(config.UpstreamNameservers) > 3 {
return fmt.Errorf("upstreamNameserver cannot have more than three entries")
}

for _, ns := range config.UpstreamNameservers {
if len(validation.IsValidIP(ns)) > 0 {
return fmt.Errorf("Invalid nameserver: %q", ns)
}
}

return nil
}
56 changes: 28 additions & 28 deletions pkg/dns/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,34 @@ import (
)

func TestValidate(t *testing.T) {
for _, testCase := range []struct {
config *Config
hasError bool
}{
{
config: &Config{Federations: map[string]string{}},
},
{
config: &Config{
Federations: map[string]string{
"abc": "d.e.f",
},
},
},
{
config: &Config{
Federations: map[string]string{
"a.b": "cdef",
},
},
hasError: true,
},
// valid
for _, testCase := range []Config{
{Federations: map[string]string{}},
{Federations: map[string]string{"abc": "d.e.f"}},
{StubDomains: map[string][]string{}},
{StubDomains: map[string][]string{"foo.com": []string{"1.2.3.4"}}},
{StubDomains: map[string][]string{"foo.com": []string{"ns.foo.com"}}},
{StubDomains: map[string][]string{
"foo.com": []string{"ns.foo.com"},
"bar.com": []string{"1.2.3.4"},
}},
{UpstreamNameservers: []string{}},
{UpstreamNameservers: []string{"1.2.3.4"}},
{UpstreamNameservers: []string{"1.2.3.4", "8.8.4.4", "8.8.8.8"}},
} {
err := testCase.config.Validate()
if !testCase.hasError {
assert.Nil(t, err, "should be valid", testCase)
} else {
assert.NotNil(t, err, "should not be valid", testCase)
}
err := testCase.Validate()
assert.Nil(t, err, "should be valid: %+v", testCase)
}

// invalid
for _, testCase := range []Config{
{Federations: map[string]string{"a.b": "cdef"}},
{StubDomains: map[string][]string{"": []string{"1.2.3.4"}}},
{StubDomains: map[string][]string{"$$$$": []string{"1.2.3.4"}}},
{StubDomains: map[string][]string{"foo": []string{"$$$$"}}},
{UpstreamNameservers: []string{"1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"}},
} {
err := testCase.Validate()
assert.NotNil(t, err, "should not be valid: %+v", testCase)
}
}
67 changes: 50 additions & 17 deletions pkg/dns/config/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package config

import (
"encoding/json"

fed "k8s.io/dns/pkg/dns/federation"

"github.com/golang/glog"
Expand Down Expand Up @@ -98,7 +100,8 @@ func (sync *kubeSync) processUpdate(result syncResult, buildUnchangedConfig bool
glog.V(4).Infof("processUpdate %+v", result)

if result.Version != sync.latestVersion {
glog.V(3).Infof("Updating config to version %v (was %v)", result.Version, sync.latestVersion)
glog.V(3).Infof("Updating config to version %v (was %v)",
result.Version, sync.latestVersion)
changed = true
sync.latestVersion = result.Version
} else {
Expand All @@ -116,32 +119,62 @@ func (sync *kubeSync) processUpdate(result syncResult, buildUnchangedConfig bool

config = &Config{}

if err = sync.updateFederations(result.Data, config); err != nil {
glog.Errorf("Invalid configuration, ignoring update")
return
for key, updateFn := range map[string]fieldUpdateFn{
"federations": updateFederations,
"stubDomains": updateStubDomains,
"upstreamNameservers": updateUpstreamNameservers,
} {
value, ok := result.Data[key]
if !ok {
glog.V(3).Infof("No %v present", key)
continue
}

if err = updateFn(key, value, config); err != nil {
glog.Errorf("Invalid configuration for %v, ignoring update: %v", key, err)
return
}
}

if err = config.Validate(); err != nil {
glog.Errorf("Invalid onfiguration: %v (value was %+v), ignoring update", err, config)
glog.Errorf("Invalid configuration: %v (value was %+v), ignoring update", err, config)
config = nil
return
}

return
}

func (sync *kubeSync) updateFederations(data map[string]string, config *Config) (err error) {
if flagValue, ok := data["federations"]; ok {
config.Federations = make(map[string]string)
if err = fed.ParseFederationsFlag(flagValue, config.Federations); err != nil {
glog.Errorf("Invalid federations value: %v (value was %q)",
err, data["federations"])
return
}
glog.V(2).Infof("Updated federations to %v", config.Federations)
} else {
glog.V(2).Infof("No federations present")
type fieldUpdateFn func(key string, data string, config *Config) error

func updateFederations(key string, value string, config *Config) error {
config.Federations = make(map[string]string)
if err := fed.ParseFederationsFlag(value, config.Federations); err != nil {
glog.Errorf("Invalid federations value: %v (value was %q)", err, value)
return err
}
glog.V(2).Infof("Updated %v to %v", key, config.Federations)

return
return nil
}

func updateStubDomains(key string, value string, config *Config) error {
config.StubDomains = make(map[string][]string)
if err := json.Unmarshal([]byte(value), &config.StubDomains); err != nil {
glog.Errorf("Invalid JSON %q: %v", value, err)
return err
}
glog.V(2).Infof("Updated %v to %v", key, config.StubDomains)

return nil
}

func updateUpstreamNameservers(key string, value string, config *Config) error {
if err := json.Unmarshal([]byte(value), &config.UpstreamNameservers); err != nil {
glog.Errorf("Invalid JSON %q: %v", value, err)
return err
}
glog.V(2).Infof("Updated %v to %v", key, config.UpstreamNameservers)

return nil
}

0 comments on commit 9cd64b6

Please sign in to comment.