Skip to content

Commit

Permalink
Merge pull request #3860 from justinsb/batching
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue.

Copy dnsprovider into our code, implement route53 batching

Fixes #3121
  • Loading branch information
Kubernetes Submit Queue authored Dec 15, 2017
2 parents ce7fe51 + 1cceb8e commit b44d894
Show file tree
Hide file tree
Showing 119 changed files with 5,236 additions and 76 deletions.
8 changes: 4 additions & 4 deletions dns-controller/cmd/dns-controller/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ go_library(
deps = [
"//dns-controller/pkg/dns:go_default_library",
"//dns-controller/pkg/watchers:go_default_library",
"//dnsprovider/pkg/dnsprovider:go_default_library",
"//dnsprovider/pkg/dnsprovider/providers/aws/route53:go_default_library",
"//dnsprovider/pkg/dnsprovider/providers/coredns:go_default_library",
"//dnsprovider/pkg/dnsprovider/providers/google/clouddns:go_default_library",
"//protokube/pkg/gossip:go_default_library",
"//protokube/pkg/gossip/dns:go_default_library",
"//protokube/pkg/gossip/dns/provider:go_default_library",
Expand All @@ -16,10 +20,6 @@ go_library(
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider/providers/aws/route53:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider/providers/coredns:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider/providers/google/clouddns:go_default_library",
],
)

Expand Down
8 changes: 4 additions & 4 deletions dns-controller/cmd/dns-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ import (
"k8s.io/client-go/rest"
"k8s.io/kops/dns-controller/pkg/dns"
"k8s.io/kops/dns-controller/pkg/watchers"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
_ "k8s.io/kops/dnsprovider/pkg/dnsprovider/providers/aws/route53"
k8scoredns "k8s.io/kops/dnsprovider/pkg/dnsprovider/providers/coredns"
_ "k8s.io/kops/dnsprovider/pkg/dnsprovider/providers/google/clouddns"
"k8s.io/kops/protokube/pkg/gossip"
gossipdns "k8s.io/kops/protokube/pkg/gossip/dns"
gossipdnsprovider "k8s.io/kops/protokube/pkg/gossip/dns/provider"
"k8s.io/kops/protokube/pkg/gossip/mesh"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
_ "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/aws/route53"
k8scoredns "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/coredns"
_ "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/google/clouddns"
)

var (
Expand Down
6 changes: 3 additions & 3 deletions dns-controller/pkg/dns/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//dns-controller/pkg/util:go_default_library",
"//dnsprovider/pkg/dnsprovider:go_default_library",
"//dnsprovider/pkg/dnsprovider/providers/coredns:go_default_library",
"//dnsprovider/pkg/dnsprovider/rrstype:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider/providers/coredns:go_default_library",
"//vendor/k8s.io/kubernetes/federation/pkg/dnsprovider/rrstype:go_default_library",
],
)

Expand Down
2 changes: 1 addition & 1 deletion dns-controller/pkg/dns/dnscache.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"time"

"github.com/golang/glog"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)

// dnsCache is a wrapper around the DNS provider, adding some caching
Expand Down
6 changes: 3 additions & 3 deletions dns-controller/pkg/dns/dnscontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import (
"sync/atomic"

"k8s.io/kops/dns-controller/pkg/util"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
k8scoredns "k8s.io/kubernetes/federation/pkg/dnsprovider/providers/coredns"
"k8s.io/kubernetes/federation/pkg/dnsprovider/rrstype"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
k8scoredns "k8s.io/kops/dnsprovider/pkg/dnsprovider/providers/coredns"
"k8s.io/kops/dnsprovider/pkg/dnsprovider/rrstype"
)

var zoneListCacheValidity = time.Minute * 15
Expand Down
2 changes: 1 addition & 1 deletion dns-controller/pkg/dns/zonespec.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"strings"

"github.com/golang/glog"
"k8s.io/kubernetes/federation/pkg/dnsprovider"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)

type ZoneSpec struct {
Expand Down
9 changes: 9 additions & 0 deletions dnsprovider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This is a (partial) copy of federation/pkg/dnsprovider from k8s.io/kubernetes.

Changes made here should be submitted upstream.

Reasons for doing this:

* Ability to fix bugs quickly
* We want to stop vendoring k8s.io/kubernetes
* The federation code is likely to move somewhere else in future
24 changes: 24 additions & 0 deletions dnsprovider/pkg/dnsprovider/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "go_default_library",
srcs = [
"dns.go",
"doc.go",
"plugins.go",
],
importpath = "k8s.io/kops/dnsprovider/pkg/dnsprovider",
visibility = ["//visibility:public"],
deps = [
"//dnsprovider/pkg/dnsprovider/rrstype:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
],
)

go_test(
name = "go_default_test",
srcs = ["dns_test.go"],
importpath = "k8s.io/kops/dnsprovider/pkg/dnsprovider",
library = ":go_default_library",
deps = ["//dnsprovider/pkg/dnsprovider/rrstype:go_default_library"],
)
114 changes: 114 additions & 0 deletions dnsprovider/pkg/dnsprovider/dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
Copyright 2016 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 dnsprovider

import (
"reflect"

"k8s.io/kops/dnsprovider/pkg/dnsprovider/rrstype"
)

// Interface is an abstract, pluggable interface for DNS providers.
type Interface interface {
// Zones returns the provider's Zones interface, or false if not supported.
Zones() (Zones, bool)
}

type Zones interface {
// List returns the managed Zones, or an error if the list operation failed.
List() ([]Zone, error)
// Add creates and returns a new managed zone, or an error if the operation failed
Add(Zone) (Zone, error)
// Remove deletes a managed zone, or returns an error if the operation failed.
Remove(Zone) error
// New allocates a new Zone, which can then be passed to Add()
// Arguments are as per the Zone interface below.
New(name string) (Zone, error)
}

type Zone interface {
// Name returns the name of the zone, e.g. "example.com"
Name() string
// ID returns the unique provider identifier for the zone
ID() string
// ResourceRecordSets returns the provider's ResourceRecordSets interface, or false if not supported.
ResourceRecordSets() (ResourceRecordSets, bool)
}

type ResourceRecordSets interface {
// List returns the ResourceRecordSets of the Zone, or an error if the list operation failed.
List() ([]ResourceRecordSet, error)
// Get returns the ResourceRecordSet list with the name in the Zone.
// This is a list because there might be multiple records of different
// types for a given name. If the named resource record sets do not
// exist, but no error occurred, the returned record set will be empty
// and error will be nil.
Get(name string) ([]ResourceRecordSet, error)
// New allocates a new ResourceRecordSet, which can then be passed to ResourceRecordChangeset Add() or Remove()
// Arguments are as per the ResourceRecordSet interface below.
New(name string, rrdatas []string, ttl int64, rrstype rrstype.RrsType) ResourceRecordSet
// StartChangeset begins a new batch operation of changes against the Zone
StartChangeset() ResourceRecordChangeset
// Zone returns the parent zone
Zone() Zone
}

// ResourceRecordChangeset accumulates a set of changes, that can then be applied with Apply
type ResourceRecordChangeset interface {
// Add adds the creation of a ResourceRecordSet in the Zone to the changeset
Add(ResourceRecordSet) ResourceRecordChangeset
// Remove adds the removal of a ResourceRecordSet in the Zone to the changeset
// The supplied ResourceRecordSet must match one of the existing recordsets (obtained via List()) exactly.
Remove(ResourceRecordSet) ResourceRecordChangeset
// Upsert adds an "create or update" operation for the ResourceRecordSet in the Zone to the changeset
// Note: the implementation may translate this into a Remove followed by an Add operation.
// If you have the pre-image, it will likely be more efficient to call Remove and Add.
Upsert(ResourceRecordSet) ResourceRecordChangeset
// Apply applies the accumulated operations to the Zone.
Apply() error
// IsEmpty returns true if there are no accumulated operations.
IsEmpty() bool
// ResourceRecordSets returns the parent ResourceRecordSets
ResourceRecordSets() ResourceRecordSets
}

type ResourceRecordSet interface {
// Name returns the name of the ResourceRecordSet, e.g. "www.example.com".
Name() string
// Rrdatas returns the Resource Record Datas of the record set.
Rrdatas() []string
// Ttl returns the time-to-live of the record set, in seconds.
Ttl() int64
// Type returns the type of the record set (A, CNAME, SRV, etc)
Type() rrstype.RrsType
}

/* ResourceRecordSetsEquivalent compares two ResourceRecordSets for semantic equivalence.
Go's equality operator doesn't work the way we want it to in this case,
hence the need for this function.
More specifically (from the Go spec):
"Two struct values are equal if their corresponding non-blank fields are equal."
In our case, there may be some private internal member variables that may not be not equal,
but we want the two structs to be considered equivalent anyway, if the fields exposed
via their interfaces are equal.
*/
func ResourceRecordSetsEquivalent(r1, r2 ResourceRecordSet) bool {
if r1.Name() == r2.Name() && reflect.DeepEqual(r1.Rrdatas(), r2.Rrdatas()) && r1.Ttl() == r2.Ttl() && r1.Type() == r2.Type() {
return true
}
return false
}
96 changes: 96 additions & 0 deletions dnsprovider/pkg/dnsprovider/dns_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
Copyright 2016 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 dnsprovider

import (
"testing"

"k8s.io/kops/dnsprovider/pkg/dnsprovider/rrstype"
)

// Compile time interface check
var _ ResourceRecordSet = record{}

type record struct {
name string
rrdatas []string
ttl int64
type_ string
}

func (r record) Name() string {
return r.name
}

func (r record) Ttl() int64 {
return r.ttl
}

func (r record) Rrdatas() []string {
return r.rrdatas
}

func (r record) Type() rrstype.RrsType {
return rrstype.RrsType(r.type_)
}

const testDNSZone string = "foo.com"

var testData = []struct {
inputs [2]record
expectedOutput bool
}{
{
[2]record{
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}, // Identical
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}}, true,
},
{
[2]record{
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}, // Identical except Name
{"bar", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}}, false,
},
{
[2]record{
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}, // Identical except Rrdata
{"foo", []string{"1.2.3.4", "5,6,7,9"}, 180, "A"}}, false,
},
{
[2]record{
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}, // Identical except Rrdata ordering reversed
{"foo", []string{"5,6,7,8", "1.2.3.4"}, 180, "A"}}, false,
},
{
[2]record{
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}, // Identical except TTL
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 150, "A"}}, false,
},
{
[2]record{
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "A"}, // Identical except Type
{"foo", []string{"1.2.3.4", "5,6,7,8"}, 180, "CNAME"}}, false,
},
}

func TestEquivalent(t *testing.T) {
for _, test := range testData {
output := ResourceRecordSetsEquivalent(test.inputs[0], test.inputs[1])
if output != test.expectedOutput {
t.Errorf("Expected equivalence comparison of %q and %q to yield %v, but it vielded %v", test.inputs[0], test.inputs[1], test.expectedOutput, output)
}
}
}
21 changes: 21 additions & 0 deletions dnsprovider/pkg/dnsprovider/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2016 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.
*/

/*
dnsprovider supplies interfaces for dns service providers (e.g. Google Cloud DNS, AWS route53, etc).
Implementations exist in the providers sub-package
*/
package dnsprovider // import "k8s.io/kops/dnsprovider/pkg/dnsprovider"
Loading

0 comments on commit b44d894

Please sign in to comment.