From e0e7a9defd4286e4aa53d51f81280baa25ca320b Mon Sep 17 00:00:00 2001 From: Erik Swets Date: Fri, 6 Apr 2018 12:12:11 +0200 Subject: [PATCH 1/4] Allow setting Cloudflare proxying by annotation --- docs/contributing/crd-source.md | 6 +- .../contributing/crd-source/crd-manifest.yaml | 9 ++- docs/tutorials/cloudflare.md | 4 ++ endpoint/endpoint.go | 21 ++++++- internal/testutils/endpoint.go | 19 ++---- internal/testutils/endpoint_test.go | 22 ++++--- provider/aws.go | 6 +- provider/aws_test.go | 16 +++-- provider/cloudflare.go | 62 +++++++++++++------ provider/cloudflare_test.go | 30 +++++++++ source/ingress.go | 1 - source/service.go | 30 +++++---- source/source.go | 25 ++++++-- 13 files changed, 179 insertions(+), 72 deletions(-) diff --git a/docs/contributing/crd-source.md b/docs/contributing/crd-source.md index 06fbea80a..ca43503d3 100644 --- a/docs/contributing/crd-source.md +++ b/docs/contributing/crd-source.md @@ -14,7 +14,11 @@ Here is typical example of [CRD API type](https://github.com/kubernetes-incubato ```go type TTL int64 type Targets []string -type ProviderSpecific map[string]string +type ProviderSpecificProperty struct { + Name string + Value string +} +type ProviderSpecific []ProviderSpecificProperty type Endpoint struct { // The hostname of the DNS record diff --git a/docs/contributing/crd-source/crd-manifest.yaml b/docs/contributing/crd-source/crd-manifest.yaml index 258404575..00b52f34c 100644 --- a/docs/contributing/crd-source/crd-manifest.yaml +++ b/docs/contributing/crd-source/crd-manifest.yaml @@ -33,7 +33,14 @@ spec: labels: type: object providerSpecific: - type: object + items: + properties: + name: + type: string + value: + type: string + type: object + type: array recordTTL: format: int64 type: integer diff --git a/docs/tutorials/cloudflare.md b/docs/tutorials/cloudflare.md index 308cb8186..2a16d1a35 100644 --- a/docs/tutorials/cloudflare.md +++ b/docs/tutorials/cloudflare.md @@ -196,3 +196,7 @@ Now that we have verified that ExternalDNS will automatically manage Cloudflare $ kubectl delete service -f nginx.yaml $ kubectl delete service -f externaldns.yaml ``` + +## Setting cloudflare-proxied on a per-ingress basis + +Using the `external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"` annotation on your ingress, you can specify if the proxy feature of Cloudflare should be enabled for that record. This setting will override the global `--cloudflare-proxied` setting. diff --git a/endpoint/endpoint.go b/endpoint/endpoint.go index ca77f36e2..2d292fb0d 100644 --- a/endpoint/endpoint.go +++ b/endpoint/endpoint.go @@ -109,8 +109,14 @@ func (t Targets) IsLess(o Targets) bool { return false } +// ProviderSpecificProperty holds the name and value of a configuration which is specific to individual DNS providers +type ProviderSpecificProperty struct { + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` +} + // ProviderSpecific holds configuration which is specific to individual DNS providers -type ProviderSpecific map[string]string +type ProviderSpecific []ProviderSpecificProperty // Endpoint is a high-level way of a connection between a service and an IP type Endpoint struct { @@ -160,10 +166,21 @@ func (e *Endpoint) WithProviderSpecific(key, value string) *Endpoint { if e.ProviderSpecific == nil { e.ProviderSpecific = ProviderSpecific{} } - e.ProviderSpecific[key] = value + + e.ProviderSpecific = append(e.ProviderSpecific, ProviderSpecificProperty{Name: key, Value: value}) return e } +// GetProviderSpecificProperty returns a ProviderSpecificProperty if the property exists. +func (e *Endpoint) GetProviderSpecificProperty(key string) (ProviderSpecificProperty, bool) { + for _, providerSpecific := range e.ProviderSpecific { + if providerSpecific.Name == key { + return providerSpecific, true + } + } + return ProviderSpecificProperty{}, false +} + func (e *Endpoint) String() string { return fmt.Sprintf("%s %d IN %s %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Targets, e.ProviderSpecific) } diff --git a/internal/testutils/endpoint.go b/internal/testutils/endpoint.go index f13a6b4c7..d804c75ea 100644 --- a/internal/testutils/endpoint.go +++ b/internal/testutils/endpoint.go @@ -17,6 +17,7 @@ limitations under the License. package testutils import ( + "reflect" "sort" "github.com/kubernetes-incubator/external-dns/endpoint" @@ -49,7 +50,7 @@ func SameEndpoint(a, b *endpoint.Endpoint) bool { return a.DNSName == b.DNSName && a.Targets.Same(b.Targets) && a.RecordType == b.RecordType && a.Labels[endpoint.OwnerLabelKey] == b.Labels[endpoint.OwnerLabelKey] && a.RecordTTL == b.RecordTTL && a.Labels[endpoint.ResourceLabelKey] == b.Labels[endpoint.ResourceLabelKey] && - SameMap(a.ProviderSpecific, b.ProviderSpecific) + SameProverSpecific(a.ProviderSpecific, b.ProviderSpecific) } // SameEndpoints compares two slices of endpoints regardless of order @@ -81,17 +82,7 @@ func SamePlanChanges(a, b map[string][]*endpoint.Endpoint) bool { SameEndpoints(a["UpdateOld"], b["UpdateOld"]) && SameEndpoints(a["UpdateNew"], b["UpdateNew"]) } -// SameMap verifies that two maps contain the same string/string key/value pairs -func SameMap(a, b map[string]string) bool { - if len(a) != len(b) { - return false - } - - for k, v := range a { - if v != b[k] { - return false - } - } - - return true +// SameProverSpecific verifies that two maps contain the same string/string key/value pairs +func SameProverSpecific(a, b endpoint.ProviderSpecific) bool { + return reflect.DeepEqual(a, b) } diff --git a/internal/testutils/endpoint_test.go b/internal/testutils/endpoint_test.go index f14ae655c..2f1204fd6 100644 --- a/internal/testutils/endpoint_test.go +++ b/internal/testutils/endpoint_test.go @@ -56,9 +56,11 @@ func ExampleSameEndpoints() { RecordTTL: endpoint.TTL(60), }, { - DNSName: "example.org", - Targets: endpoint.Targets{"load-balancer.org"}, - ProviderSpecific: endpoint.ProviderSpecific{"foo": "bar"}, + DNSName: "example.org", + Targets: endpoint.Targets{"load-balancer.org"}, + ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{Name: "foo", Value: "bar"}, + }, }, } sort.Sort(byAllFields(eps)) @@ -66,11 +68,11 @@ func ExampleSameEndpoints() { fmt.Println(ep) } // Output: - // abc.com 0 IN A 1.2.3.4 map[] - // abc.com 0 IN TXT something map[] - // bbc.com 0 IN CNAME foo.com map[] - // cbc.com 60 IN CNAME foo.com map[] - // example.org 0 IN load-balancer.org map[] - // example.org 0 IN load-balancer.org map[foo:bar] - // example.org 0 IN TXT load-balancer.org map[] + // abc.com 0 IN A 1.2.3.4 [] + // abc.com 0 IN TXT something [] + // bbc.com 0 IN CNAME foo.com [] + // cbc.com 60 IN CNAME foo.com [] + // example.org 0 IN load-balancer.org [] + // example.org 0 IN load-balancer.org [{foo bar}] + // example.org 0 IN TXT load-balancer.org [] } diff --git a/provider/aws.go b/provider/aws.go index 7ec5e79aa..33fd0b5cc 100644 --- a/provider/aws.go +++ b/provider/aws.go @@ -371,8 +371,8 @@ func (p *AWSProvider) newChange(action string, endpoint *endpoint.Endpoint) *rou if isAWSLoadBalancer(endpoint) { evalTargetHealth := p.evaluateTargetHealth - if _, ok := endpoint.ProviderSpecific[providerSpecificEvaluateTargetHealth]; ok { - evalTargetHealth = endpoint.ProviderSpecific[providerSpecificEvaluateTargetHealth] == "true" + if prop, ok := endpoint.GetProviderSpecificProperty(providerSpecificEvaluateTargetHealth); ok { + evalTargetHealth = prop.Value == "true" } change.ResourceRecordSet.Type = aws.String(route53.RRTypeA) @@ -549,7 +549,7 @@ func isAWSLoadBalancer(ep *endpoint.Endpoint) bool { // isAWSAlias determines if a given hostname belongs to an AWS Alias record by doing an reverse lookup. func isAWSAlias(ep *endpoint.Endpoint, addrs []*endpoint.Endpoint) string { - if val, exists := ep.ProviderSpecific["alias"]; ep.RecordType == endpoint.RecordTypeCNAME && exists && val == "true" { + if prop, exists := ep.GetProviderSpecificProperty("alias"); ep.RecordType == endpoint.RecordTypeCNAME && exists && prop.Value == "true" { for _, addr := range addrs { if addr.DNSName == ep.Targets[0] { if hostedZone := canonicalHostedZone(addr.Targets[0]); hostedZone != "" { diff --git a/provider/aws_test.go b/provider/aws_test.go index 6852b6df2..d1a37cc89 100644 --- a/provider/aws_test.go +++ b/provider/aws_test.go @@ -781,7 +781,10 @@ func TestAWSCreateRecordsWithALIAS(t *testing.T) { Targets: endpoint.Targets{"foo.eu-central-1.elb.amazonaws.com"}, RecordType: endpoint.RecordTypeCNAME, ProviderSpecific: endpoint.ProviderSpecific{ - providerSpecificEvaluateTargetHealth: key, + endpoint.ProviderSpecificProperty{ + Name: providerSpecificEvaluateTargetHealth, + Value: key, + }, }, }, } @@ -832,9 +835,14 @@ func TestAWSisAWSAlias(t *testing.T) { {"foo.example.org", endpoint.RecordTypeCNAME, "true", ""}, } { ep := &endpoint.Endpoint{ - Targets: endpoint.Targets{tc.target}, - RecordType: tc.recordType, - ProviderSpecific: map[string]string{"alias": tc.alias}, + Targets: endpoint.Targets{tc.target}, + RecordType: tc.recordType, + ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "alias", + Value: tc.alias, + }, + }, } addrs := []*endpoint.Endpoint{ { diff --git a/provider/cloudflare.go b/provider/cloudflare.go index 75e24f414..ffb6bf81c 100644 --- a/provider/cloudflare.go +++ b/provider/cloudflare.go @@ -19,6 +19,7 @@ package provider import ( "fmt" "os" + "strconv" "strings" cloudflare "github.com/cloudflare/cloudflare-go" @@ -26,6 +27,7 @@ import ( "github.com/kubernetes-incubator/external-dns/endpoint" "github.com/kubernetes-incubator/external-dns/plan" + "github.com/kubernetes-incubator/external-dns/source" ) const ( @@ -93,10 +95,10 @@ func (z zoneService) DeleteDNSRecord(zoneID, recordID string) error { type CloudFlareProvider struct { Client cloudFlareDNS // only consider hosted zones managing domains ending in this suffix - domainFilter DomainFilter - zoneIDFilter ZoneIDFilter - proxied bool - DryRun bool + domainFilter DomainFilter + zoneIDFilter ZoneIDFilter + proxiedByDefault bool + DryRun bool } // cloudFlareChange differentiates between ChangActions @@ -106,7 +108,7 @@ type cloudFlareChange struct { } // NewCloudFlareProvider initializes a new CloudFlare DNS based Provider. -func NewCloudFlareProvider(domainFilter DomainFilter, zoneIDFilter ZoneIDFilter, proxied bool, dryRun bool) (*CloudFlareProvider, error) { +func NewCloudFlareProvider(domainFilter DomainFilter, zoneIDFilter ZoneIDFilter, proxiedByDefault bool, dryRun bool) (*CloudFlareProvider, error) { // initialize via API email and API key and returns new API object config, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL")) if err != nil { @@ -114,11 +116,11 @@ func NewCloudFlareProvider(domainFilter DomainFilter, zoneIDFilter ZoneIDFilter, } provider := &CloudFlareProvider{ //Client: config, - Client: zoneService{config}, - domainFilter: domainFilter, - zoneIDFilter: zoneIDFilter, - proxied: proxied, - DryRun: dryRun, + Client: zoneService{config}, + domainFilter: domainFilter, + zoneIDFilter: zoneIDFilter, + proxiedByDefault: proxiedByDefault, + DryRun: dryRun, } return provider, nil } @@ -173,11 +175,13 @@ func (p *CloudFlareProvider) Records() ([]*endpoint.Endpoint, error) { // ApplyChanges applies a given set of changes in a given zone. func (p *CloudFlareProvider) ApplyChanges(changes *plan.Changes) error { + proxiedByDefault := p.proxiedByDefault + combinedChanges := make([]*cloudFlareChange, 0, len(changes.Create)+len(changes.UpdateNew)+len(changes.Delete)) - combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareCreate, changes.Create, p.proxied)...) - combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareUpdate, changes.UpdateNew, p.proxied)...) - combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareDelete, changes.Delete, p.proxied)...) + combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareCreate, changes.Create, proxiedByDefault)...) + combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareUpdate, changes.UpdateNew, proxiedByDefault)...) + combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareDelete, changes.Delete, proxiedByDefault)...) return p.submitChanges(combinedChanges) } @@ -270,21 +274,20 @@ func (p *CloudFlareProvider) getRecordID(records []cloudflare.DNSRecord, record } // newCloudFlareChanges returns a collection of Changes based on the given records and action. -func newCloudFlareChanges(action string, endpoints []*endpoint.Endpoint, proxied bool) []*cloudFlareChange { +func newCloudFlareChanges(action string, endpoints []*endpoint.Endpoint, proxiedByDefault bool) []*cloudFlareChange { changes := make([]*cloudFlareChange, 0, len(endpoints)) for _, endpoint := range endpoints { - changes = append(changes, newCloudFlareChange(action, endpoint, proxied)) + changes = append(changes, newCloudFlareChange(action, endpoint, proxiedByDefault)) } return changes } -func newCloudFlareChange(action string, endpoint *endpoint.Endpoint, proxied bool) *cloudFlareChange { +func newCloudFlareChange(action string, endpoint *endpoint.Endpoint, proxiedByDefault bool) *cloudFlareChange { ttl := defaultCloudFlareRecordTTL - if proxied && (cloudFlareTypeNotSupported[endpoint.RecordType] || strings.Contains(endpoint.DNSName, "*")) { - proxied = false - } + proxied := shouldBeProxied(endpoint, proxiedByDefault) + if endpoint.RecordTTL.IsConfigured() { ttl = int(endpoint.RecordTTL) } @@ -300,3 +303,24 @@ func newCloudFlareChange(action string, endpoint *endpoint.Endpoint, proxied boo }, } } + +func shouldBeProxied(endpoint *endpoint.Endpoint, proxiedByDefault bool) bool { + proxied := proxiedByDefault + + for _, v := range endpoint.ProviderSpecific { + if v.Name == source.CloudflareProxiedKey { + b, err := strconv.ParseBool(v.Value) + if err != nil { + log.Errorf("Failed to parse annotation [%s]: %v", source.CloudflareProxiedKey, err) + } else { + proxied = b + } + break + } + } + + if cloudFlareTypeNotSupported[endpoint.RecordType] || strings.Contains(endpoint.DNSName, "*") { + proxied = false + } + return proxied +} diff --git a/provider/cloudflare_test.go b/provider/cloudflare_test.go index cfa54ca21..00389e9ce 100644 --- a/provider/cloudflare_test.go +++ b/provider/cloudflare_test.go @@ -368,6 +368,36 @@ func TestNewCloudFlareChangeNoProxied(t *testing.T) { assert.False(t, change.ResourceRecordSet.Proxied) } +func TestNewCloudFlareProxiedAnnotationTrue(t *testing.T) { + change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: "A", Targets: endpoint.Targets{"target"}, ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied", + Value: "true", + }, + }}, false) + assert.True(t, change.ResourceRecordSet.Proxied) +} + +func TestNewCloudFlareProxiedAnnotationFalse(t *testing.T) { + change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: "A", Targets: endpoint.Targets{"target"}, ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied", + Value: "false", + }, + }}, true) + assert.False(t, change.ResourceRecordSet.Proxied) +} + +func TestNewCloudFlareProxiedAnnotationIllegalValue(t *testing.T) { + change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: "A", Targets: endpoint.Targets{"target"}, ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied", + Value: "asdaslkjndaslkdjals", + }, + }}, false) + assert.False(t, change.ResourceRecordSet.Proxied) +} + func TestNewCloudFlareChangeProxiable(t *testing.T) { var cloudFlareTypes = []struct { recordType string diff --git a/source/ingress.go b/source/ingress.go index cbda3cd92..056b8dd6f 100644 --- a/source/ingress.go +++ b/source/ingress.go @@ -232,7 +232,6 @@ func endpointsFromIngress(ing *v1beta1.Ingress) []*endpoint.Endpoint { for _, hostname := range hostnameList { endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...) } - return endpoints } diff --git a/source/service.go b/source/service.go index 28cb1b9cd..1242763fe 100644 --- a/source/service.go +++ b/source/service.go @@ -218,9 +218,10 @@ func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service, nodeTargets endp return nil, fmt.Errorf("failed to apply template on service %s: %v", svc.String(), err) } + providerSpecific := getProviderSpecificAnnotations(svc.Annotations) hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",") for _, hostname := range hostnameList { - endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets)...) + endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets, providerSpecific)...) } return endpoints, nil @@ -230,9 +231,10 @@ func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service, nodeTargets endp func (sc *serviceSource) endpoints(svc *v1.Service, nodeTargets endpoint.Targets) []*endpoint.Endpoint { var endpoints []*endpoint.Endpoint + providerSpecific := getProviderSpecificAnnotations(svc.Annotations) hostnameList := getHostnamesFromAnnotations(svc.Annotations) for _, hostname := range hostnameList { - endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets)...) + endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets, providerSpecific)...) } return endpoints @@ -288,7 +290,7 @@ func (sc *serviceSource) setResourceLabel(service v1.Service, endpoints []*endpo } } -func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, nodeTargets endpoint.Targets) []*endpoint.Endpoint { +func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, nodeTargets endpoint.Targets, providerSpecific endpoint.ProviderSpecific) []*endpoint.Endpoint { hostname = strings.TrimSuffix(hostname, ".") ttl, err := getTTLFromAnnotations(svc.Annotations) if err != nil { @@ -296,19 +298,21 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, nod } epA := &endpoint.Endpoint{ - RecordTTL: ttl, - RecordType: endpoint.RecordTypeA, - Labels: endpoint.NewLabels(), - Targets: make(endpoint.Targets, 0, defaultTargetsCapacity), - DNSName: hostname, + RecordTTL: ttl, + RecordType: endpoint.RecordTypeA, + Labels: endpoint.NewLabels(), + Targets: make(endpoint.Targets, 0, defaultTargetsCapacity), + DNSName: hostname, + ProviderSpecific: providerSpecific, } epCNAME := &endpoint.Endpoint{ - RecordTTL: ttl, - RecordType: endpoint.RecordTypeCNAME, - Labels: endpoint.NewLabels(), - Targets: make(endpoint.Targets, 0, defaultTargetsCapacity), - DNSName: hostname, + RecordTTL: ttl, + RecordType: endpoint.RecordTypeCNAME, + Labels: endpoint.NewLabels(), + Targets: make(endpoint.Targets, 0, defaultTargetsCapacity), + DNSName: hostname, + ProviderSpecific: providerSpecific, } var endpoints []*endpoint.Endpoint diff --git a/source/source.go b/source/source.go index 338397dfc..c4e856fb9 100644 --- a/source/source.go +++ b/source/source.go @@ -41,6 +41,12 @@ const ( controllerAnnotationValue = "dns-controller" ) +// Provider-specific annotations +const ( + // The annotation used for determining if traffic will go through Cloudflare + CloudflareProxiedKey = "external-dns.alpha.kubernetes.io/cloudflare-proxied" +) + const ( ttlMinimum = 1 ttlMaximum = math.MaxUint32 @@ -72,7 +78,6 @@ func getHostnamesFromAnnotations(annotations map[string]string) []string { if !exists { return nil } - return strings.Split(strings.Replace(hostnameAnnotation, " ", "", -1), ",") } @@ -82,10 +87,22 @@ func getAliasFromAnnotations(annotations map[string]string) bool { } func getProviderSpecificAnnotations(annotations map[string]string) endpoint.ProviderSpecific { - if getAliasFromAnnotations(annotations) { - return map[string]string{"alias": "true"} + providerSpecificAnnotations := endpoint.ProviderSpecific{} + + v, exists := annotations[CloudflareProxiedKey] + if exists { + providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{ + Name: CloudflareProxiedKey, + Value: v, + }) } - return map[string]string{} + if getAliasFromAnnotations(annotations) { + providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{ + Name: "alias", + Value: "true", + }) + } + return providerSpecificAnnotations } // getTargetsFromTargetAnnotation gets endpoints from optional "target" annotation. From a5441bddea0a04a430cde2565644d6a2a4032d92 Mon Sep 17 00:00:00 2001 From: Erik Swets Date: Fri, 11 Jan 2019 20:15:54 +0100 Subject: [PATCH 2/4] Support updating ProviderSpecific property. --- Gopkg.lock | 328 ++++++----------------------------------- Gopkg.toml | 4 + plan/plan.go | 7 +- plan/plan_test.go | 71 +++++++-- provider/cloudflare.go | 2 +- 5 files changed, 120 insertions(+), 292 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 7ae69152a..29912ae53 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,66 +2,53 @@ [[projects]] - digest = "1:ae9d0182a5cf7dbb025a8fc5821234cc1f26ca342fc41d951a99f71b9adc1b87" name = "cloud.google.com/go" packages = [ "compute/metadata", - "internal", + "internal" ] - pruneopts = "" revision = "3b1ae45394a234c385be014e9a488f2bb6eef821" [[projects]] - digest = "1:fd38e3b8c27cab6561a7d2e8557205c3ca5c57cbb6d3a79e10f22e73e84fd776" name = "github.com/Azure/azure-sdk-for-go" packages = ["arm/dns"] - pruneopts = "" revision = "2629e2dfcfeab50896230140542c3b9d89b35ae1" version = "v10.0.4-beta" [[projects]] - digest = "1:f719ef698feb8da2923ebda9a8d553b977320b02182f3797e185202e588a94b1" name = "github.com/Azure/go-autorest" packages = [ "autorest", "autorest/adal", "autorest/azure", "autorest/date", - "autorest/to", + "autorest/to" ] - pruneopts = "" revision = "aa2a4534ab680e938d933870f58f23f77e0e208e" version = "v10.9.0" [[projects]] - digest = "1:7dc69d1597e4773ec5f64e5c078d55f0f011bb05ec0435346d0649ad978a23fd" name = "github.com/alecthomas/kingpin" packages = ["."] - pruneopts = "" revision = "1087e65c9441605df944fb12c33f0fe7072d18ca" version = "v2.2.5" [[projects]] branch = "master" - digest = "1:a74730e052a45a3fab1d310fdef2ec17ae3d6af16228421e238320846f2aaec8" name = "github.com/alecthomas/template" packages = [ ".", - "parse", + "parse" ] - pruneopts = "" revision = "a0175ee3bccc567396460bf5acd36800cb10c49c" [[projects]] branch = "master" - digest = "1:8483994d21404c8a1d489f6be756e25bfccd3b45d65821f25695577791a08e68" name = "github.com/alecthomas/units" packages = ["."] - pruneopts = "" revision = "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a" [[projects]] - digest = "1:d2dc5d0ccc137594ea6fb3870964967b96b43daac19b8093930c7b02873fd5ca" name = "github.com/aliyun/alibaba-cloud-sdk-go" packages = [ "sdk", @@ -74,14 +61,12 @@ "sdk/responses", "sdk/utils", "services/alidns", - "services/pvtz", + "services/pvtz" ] - pruneopts = "" revision = "cad214d7d71fba7883fcf3b7e550ba782c15b400" version = "1.27.7" [[projects]] - digest = "1:1c82dd6a02941a3c4f23a32eca182717ab79691939e97d6b971466b780f06eea" name = "github.com/aws/aws-sdk-go" packages = [ "aws", @@ -113,30 +98,24 @@ "private/protocol/xml/xmlutil", "service/route53", "service/servicediscovery", - "service/sts", + "service/sts" ] - pruneopts = "" revision = "9b0098a71f6d4d473a26ec8ad3c2feaac6eb1da6" version = "v1.13.32" [[projects]] branch = "master" - digest = "1:0c5485088ce274fac2e931c1b979f2619345097b39d91af3239977114adf0320" name = "github.com/beorn7/perks" packages = ["quantile"] - pruneopts = "" revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9" [[projects]] - digest = "1:85fd00554a6ed5b33687684b76635d532c74141508b5bce2843d85e8a3c9dc91" name = "github.com/cloudflare/cloudflare-go" packages = ["."] - pruneopts = "" revision = "4c6994ac3877fbb627766edadc67f4e816e8c890" version = "v0.7.4" [[projects]] - digest = "1:eaeede87b418b97f9dee473f8940fd9b65ca5cdac0503350c7c8f8965ea3cf4d" name = "github.com/coreos/etcd" packages = [ "auth/authpb", @@ -144,108 +123,84 @@ "etcdserver/api/v3rpc/rpctypes", "etcdserver/etcdserverpb", "mvcc/mvccpb", - "pkg/types", + "pkg/types" ] - pruneopts = "" revision = "1b3ac99e8a431b381e633802cc42fe70e663baf5" version = "v3.2.15" [[projects]] - digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b" name = "github.com/davecgh/go-spew" packages = ["spew"] - pruneopts = "" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] branch = "master" - digest = "1:dc166ce7345c060c2153561130d6d49ac580c804226ac675e368d533b36eb169" name = "github.com/denverdino/aliyungo" packages = [ "metadata", - "util", + "util" ] - pruneopts = "" revision = "69560d9530f5265ba00ffad2520d7ef01c2cddd4" [[projects]] - digest = "1:6098222470fe0172157ce9bbef5d2200df4edde17ee649c5d6e48330e4afa4c6" name = "github.com/dgrijalva/jwt-go" packages = ["."] - pruneopts = "" revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" version = "v3.2.0" [[projects]] - digest = "1:32d1941b093bb945de75b0276348494be318d34f3df39c4413d61e002c800bc6" name = "github.com/digitalocean/godo" packages = [ ".", - "context", + "context" ] - pruneopts = "" revision = "77ea48de76a7b31b234d854f15d003c68bb2fb90" version = "v1.1.1" [[projects]] - digest = "1:5ffd39844bdd1259a6227d544f582c6686ce43c8c44399a46052fe3bd2bed93c" name = "github.com/dnsimple/dnsimple-go" packages = ["dnsimple"] - pruneopts = "" revision = "d1105abc03b313d7b8d9b04364f6bd053b346e59" version = "v0.14.0" [[projects]] - digest = "1:e17d18b233f506404061c27ac4a08624dad38dcd0d49f9cfdae67a7772a4fb8c" name = "github.com/exoscale/egoscale" packages = ["."] - pruneopts = "" revision = "c6d915cb993f1a54f604acefc0fc15cf6578a87a" version = "v0.11.0" [[projects]] branch = "master" - digest = "1:ae7fb2062735e966ab69d14d2a091f3778b0d676dc8d1f01d092bcb0fb8ed45b" name = "github.com/ffledgling/pdns-go" packages = ["."] - pruneopts = "" revision = "524e7daccd99651cdb56426eb15b7d61f9597a5c" [[projects]] - digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" name = "github.com/ghodss/yaml" packages = ["."] - pruneopts = "" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] - digest = "1:a00483fe4106b86fb1187a92b5cf6915c85f294ed4c129ccbe7cb1f1a06abd46" name = "github.com/go-ini/ini" packages = ["."] - pruneopts = "" revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a" version = "v1.32.0" [[projects]] - digest = "1:8e67153fc0a9fb0d6c9707e36cf80e217a012364307b222eb4ba6828f7e881e6" name = "github.com/go-resty/resty" packages = ["."] - pruneopts = "" revision = "97a15579492cd5f35632499f315d7a8df94160a1" version = "v1.8.0" [[projects]] - digest = "1:54d5c6a784a9de9c836fc070d51d0689c3e99ee6d24dba8a36f0762039dae830" name = "github.com/gogo/googleapis" packages = ["google/rpc"] - pruneopts = "" revision = "8558fb44d2f1fc223118afc694129d2c2d2924d1" version = "v1.1.0" [[projects]] - digest = "1:6e73003ecd35f4487a5e88270d3ca0a81bc80dc88053ac7e4dcfec5fba30d918" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -253,23 +208,19 @@ "proto", "protoc-gen-gogo/descriptor", "sortkeys", - "types", + "types" ] - pruneopts = "" revision = "636bf0302bc95575d69441b25a2603156ffdddf1" version = "v1.1.1" [[projects]] branch = "master" - digest = "1:b12aff239810a9fa71e901a712a52f9da4c6e536852e943be693dec1d4519dfd" name = "github.com/golang/glog" packages = ["."] - pruneopts = "" revision = "3fa5b9870d1d29f6d7907b29f1ae8c6eeb403829" source = "github.com/kubermatic/glog-logrus" [[projects]] - digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18" name = "github.com/golang/protobuf" packages = [ "jsonpb", @@ -279,50 +230,51 @@ "ptypes/any", "ptypes/duration", "ptypes/struct", - "ptypes/timestamp", + "ptypes/timestamp" ] - pruneopts = "" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" version = "v1.2.0" [[projects]] branch = "master" - digest = "1:be28c0531a755f2178acf1e327e6f5a8a3968feb5f2567cdc968064253141751" name = "github.com/google/btree" packages = ["."] - pruneopts = "" revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4" +[[projects]] + name = "github.com/google/go-cmp" + packages = [ + "cmp", + "cmp/internal/diff", + "cmp/internal/function", + "cmp/internal/value" + ] + revision = "3af367b6b30c263d47e8895973edcca9a49cf029" + version = "v0.2.0" + [[projects]] branch = "master" - digest = "1:9abc49f39e3e23e262594bb4fb70abf74c0c99e94f99153f43b143805e850719" name = "github.com/google/go-querystring" packages = ["query"] - pruneopts = "" revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a" [[projects]] - digest = "1:a2823c34933d4a2b36284f617f483d51fe156a443923284b3660f183dcfa3338" name = "github.com/google/gofuzz" packages = ["."] - pruneopts = "" revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c" [[projects]] - digest = "1:16b2837c8b3cf045fa2cdc82af0cf78b19582701394484ae76b2c3bc3c99ad73" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", - "extensions", + "extensions" ] - pruneopts = "" revision = "7c663266750e7d82587642f65e60bc4083f1f84e" version = "v0.2.0" [[projects]] branch = "master" - digest = "1:54a44d48a24a104e078ef5f94d82f025a6be757e7c42b4370c621a3928d6ab7c" name = "github.com/gophercloud/gophercloud" packages = [ ".", @@ -333,336 +285,258 @@ "openstack/identity/v2/tokens", "openstack/identity/v3/tokens", "openstack/utils", - "pagination", + "pagination" ] - pruneopts = "" revision = "bfc4756e1a693a850d7d459f4b28b21f35a24b5a" [[projects]] - digest = "1:dbbeb8ddb0be949954c8157ee8439c2adfd8dc1c9510eb44a6e58cb68c3dce28" name = "github.com/gorilla/context" packages = ["."] - pruneopts = "" revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" version = "v1.1.1" [[projects]] - digest = "1:c2c8666b4836c81a1d247bdf21c6a6fc1ab586538ab56f74437c2e0df5c375e1" name = "github.com/gorilla/mux" packages = ["."] - pruneopts = "" revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" version = "v1.6.2" [[projects]] branch = "master" - digest = "1:009a1928b8c096338b68b5822d838a72b4d8520715c1463614476359f3282ec8" name = "github.com/gregjones/httpcache" packages = [ ".", - "diskcache", + "diskcache" ] - pruneopts = "" revision = "9cad4c3443a7200dd6400aef47183728de563a38" [[projects]] - digest = "1:8e3bd93036b4a925fe2250d3e4f38f21cadb8ef623561cd80c3c50c114b13201" name = "github.com/hashicorp/errwrap" packages = ["."] - pruneopts = "" revision = "8a6fb523712970c966eefc6b39ed2c5e74880354" version = "v1.0.0" [[projects]] branch = "master" - digest = "1:72308fdd6d5ef61106a95be7ca72349a5565809042b6426a3cfb61d99483b824" name = "github.com/hashicorp/go-multierror" packages = ["."] - pruneopts = "" revision = "886a7fbe3eb1c874d46f623bfa70af45f425b3d1" [[projects]] - digest = "1:3313a63031ae281e5f6fd7b0bbca733dfa04d2429df86519e3b4d4c016ccb836" name = "github.com/hashicorp/golang-lru" packages = [ ".", - "simplelru", + "simplelru" ] - pruneopts = "" revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768" version = "v0.5.0" [[projects]] - digest = "1:af7e132906cb360f4d7c34a9e1434825467f21c4ff5c521ad4cc5b55352876a8" name = "github.com/imdario/mergo" packages = ["."] - pruneopts = "" revision = "6633656539c1639d9d78127b7d47c622b5d7b6dc" [[projects]] - digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] - pruneopts = "" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] branch = "master" - digest = "1:e0a13d0a368c028716e78448db972657b5292c7238d61405e8289f47c05c8706" name = "github.com/infobloxopen/infoblox-go-client" packages = ["."] - pruneopts = "" revision = "61dc5f9b0a655ebf43026f0d8a837ad1e28e4b96" [[projects]] - digest = "1:6f49eae0c1e5dab1dafafee34b207aeb7a42303105960944828c2079b92fc88e" name = "github.com/jmespath/go-jmespath" packages = ["."] - pruneopts = "" revision = "0b12d6b5" [[projects]] - digest = "1:53ac4e911e12dde0ab68655e2006449d207a5a681f084974da2b06e5dbeaca72" name = "github.com/json-iterator/go" packages = ["."] - pruneopts = "" revision = "ab8a2e0c74be9d3be70b3184d9acc634935ded82" version = "1.1.4" [[projects]] - digest = "1:1c88ec29544b281964ed7a9a365b2802a523cd06c50cdee87eb3eec89cd864f4" name = "github.com/kubernetes/repo-infra" packages = ["verify/boilerplate/test"] - pruneopts = "" revision = "c2f9667a4c29e70a39b0e89db2d4f0cab907dbee" [[projects]] - digest = "1:7c23a751ce2f84663fa411acb87eae0da2d09c39a8e99b08bd8f65fae75d8928" name = "github.com/linki/instrumented_http" packages = ["."] - pruneopts = "" revision = "508103cfb3b315fa9752b5bcd4fb2d97bbc26d89" version = "v0.2.0" [[projects]] - digest = "1:1c41354ef11c9dbae2fe1ceee8369fcb2634977ba07e701e19ea53e8742c5420" name = "github.com/linode/linodego" packages = ["."] - pruneopts = "" revision = "7edbc87f0140b7561dbc20458877a56bdded5eb8" version = "v0.3.0" [[projects]] branch = "master" - digest = "1:63722a4b1e1717be7b98fc686e0b30d5e7f734b9e93d7dee86293b6deab7ea28" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] - pruneopts = "" revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" [[projects]] - digest = "1:4c8d8358c45ba11ab7bb15df749d4df8664ff1582daead28bae58cf8cbe49890" name = "github.com/miekg/dns" packages = ["."] - pruneopts = "" revision = "5a2b9fab83ff0f8bfc99684bd5f43a37abe560f1" version = "v1.0.8" [[projects]] - digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd" name = "github.com/modern-go/concurrent" packages = ["."] - pruneopts = "" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] - digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" name = "github.com/modern-go/reflect2" packages = ["."] - pruneopts = "" revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" version = "1.0.1" [[projects]] - digest = "1:11c58e19ff7ce22740423bb933f1ddca3bf575def40d5ac3437ec12871b1648b" name = "github.com/natefinch/lumberjack" packages = ["."] - pruneopts = "" revision = "a96e63847dc3c67d17befa69c303767e2f84e54f" version = "v2.1" [[projects]] - digest = "1:d8b5d0ecca348c835914a1ed8589f17a6a7f309befab7327b0470324531f7ac4" name = "github.com/nesv/go-dynect" packages = ["dynect"] - pruneopts = "" revision = "cdd946344b54bdf7dbeac406c2f1fe93150f08ea" version = "v0.6.0" [[projects]] - digest = "1:70df8e71a953626770223d4982801fa73e7e99cbfcca068b95127f72af9b9edd" name = "github.com/oracle/oci-go-sdk" packages = [ "common", - "dns", + "dns" ] - pruneopts = "" revision = "a2ded717dc4bb4916c0416ec79f81718b576dbc4" version = "v1.8.0" [[projects]] branch = "master" - digest = "1:c24598ffeadd2762552269271b3b1510df2d83ee6696c1e543a0ff653af494bc" name = "github.com/petar/GoLLRB" packages = ["llrb"] - pruneopts = "" revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" [[projects]] - digest = "1:b46305723171710475f2dd37547edd57b67b9de9f2a6267cafdd98331fd6897f" name = "github.com/peterbourgon/diskv" packages = ["."] - pruneopts = "" revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" version = "v2.0.1" [[projects]] - digest = "1:cf172c58bb2a13ed39ea1c9e79525567c63bcc2c4afbb6cf023e87b31780f249" name = "github.com/pkg/errors" packages = ["."] - pruneopts = "" revision = "f15c970de5b76fac0b59abb32d62c17cc7bed265" [[projects]] - digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" name = "github.com/pmezard/go-difflib" packages = ["difflib"] - pruneopts = "" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] - digest = "1:2f69dc6b2685b31a1a410ef697410aa8a669704fb201d45dbd8c1911728afa75" name = "github.com/prometheus/client_golang" packages = [ "prometheus", - "prometheus/promhttp", + "prometheus/promhttp" ] - pruneopts = "" revision = "967789050ba94deca04a5e84cce8ad472ce313c1" version = "v0.9.0-pre1" [[projects]] branch = "master" - digest = "1:60aca47f4eeeb972f1b9da7e7db51dee15ff6c59f7b401c1588b8e6771ba15ef" name = "github.com/prometheus/client_model" packages = ["go"] - pruneopts = "" revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" [[projects]] branch = "master" - digest = "1:e3aa5178be4fc4ae8cdb37d11c02f7490c00450a9f419e6aa84d02d3b47e90d2" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model", + "model" ] - pruneopts = "" revision = "2e54d0b93cba2fd133edc32211dcc32c06ef72ca" [[projects]] - digest = "1:a6a85fc81f2a06ccac3d45005523afbeee45138d781d4f3cb7ad9889d5c65aab" name = "github.com/prometheus/procfs" packages = [ ".", - "xfs", + "xfs" ] - pruneopts = "" revision = "a6e9df898b1336106c743392c48ee0b71f5c4efa" [[projects]] - digest = "1:7f569d906bdd20d906b606415b7d794f798f91a62fcfb6a4daa6d50690fb7a3f" name = "github.com/satori/go.uuid" packages = ["."] - pruneopts = "" revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" version = "v1.2.0" [[projects]] - digest = "1:3ac248add5bb40a3c631c5334adcd09aa72d15af2768a5bc0274084ea7b2e5ba" name = "github.com/sirupsen/logrus" packages = ["."] - pruneopts = "" revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e" version = "v1.0.3" [[projects]] - digest = "1:a1403cc8a94b8d7956ee5e9694badef0e7b051af289caad1cf668331e3ffa4f6" name = "github.com/spf13/cobra" packages = ["."] - pruneopts = "" revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" version = "v0.0.3" [[projects]] - digest = "1:0a52bcb568386d98f4894575d53ce3e456f56471de6897bb8b9de13c33d9340e" name = "github.com/spf13/pflag" packages = ["."] - pruneopts = "" revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" version = "v1.0.2" [[projects]] - digest = "1:306417ea2f31ea733df356a2b895de63776b6a5107085b33458e5cd6eb1d584d" name = "github.com/stretchr/objx" packages = ["."] - pruneopts = "" revision = "facf9a85c22f48d2f52f2380e4efce1768749a89" version = "v0.1" [[projects]] - digest = "1:a30066593578732a356dc7e5d7f78d69184ca65aeeff5939241a3ab10559bb06" name = "github.com/stretchr/testify" packages = [ "assert", "mock", "require", - "suite", + "suite" ] - pruneopts = "" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" version = "v1.2.1" [[projects]] branch = "master" - digest = "1:81f435c83e3523a7ee3f277769727f73ca66218ca8188d96a0935a4841b47a76" name = "github.com/tent/http-link-go" packages = ["."] - pruneopts = "" revision = "ac974c61c2f990f4115b119354b5e0b47550e888" [[projects]] - digest = "1:74f86c458e82e1c4efbab95233e0cf51b7cc02dc03193be9f62cd81224e10401" name = "go.uber.org/atomic" packages = ["."] - pruneopts = "" revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289" version = "v1.3.2" [[projects]] - digest = "1:22c7effcb4da0eacb2bb1940ee173fac010e9ef3c691f5de4b524d538bd980f5" name = "go.uber.org/multierr" packages = ["."] - pruneopts = "" revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a" version = "v1.1.0" [[projects]] - digest = "1:246f378f80fba6fcf0f191c486b6613265abd2bc0f2fa55a36b928c67352021e" name = "go.uber.org/zap" packages = [ ".", @@ -671,26 +545,22 @@ "internal/color", "internal/exit", "zapcore", - "zapgrpc", + "zapgrpc" ] - pruneopts = "" revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982" version = "v1.9.1" [[projects]] branch = "master" - digest = "1:b2d8b39397ca07929a3de3a3fd2b6ca4c8d48e9cadaa7cf2b083e27fd9e78107" name = "golang.org/x/crypto" packages = [ "ed25519", "ed25519/internal/edwards25519", - "ssh/terminal", + "ssh/terminal" ] - pruneopts = "" revision = "0709b304e793a5edb4a2c0145f281ecdc20838a4" [[projects]] - digest = "1:782723d6fc27d202f1943219d68d58b3f6bcab6212c85294b1ddd8b586b1d356" name = "golang.org/x/net" packages = [ "bpf", @@ -706,36 +576,30 @@ "ipv4", "ipv6", "publicsuffix", - "trace", + "trace" ] - pruneopts = "" revision = "161cd47e91fd58ac17490ef4d742dc98bb4cf60e" [[projects]] - digest = "1:dad5a319c4710358be1f2bf68f9fb7f90a71d7c641221b79801d5667b28f19e3" name = "golang.org/x/oauth2" packages = [ ".", "google", "internal", "jws", - "jwt", + "jwt" ] - pruneopts = "" revision = "3c3a985cb79f52a3190fbc056984415ca6763d01" [[projects]] - digest = "1:39d88a855976e160babdd254802e1c2ae75ed380328c39742b57928852da6207" name = "golang.org/x/sys" packages = [ "unix", - "windows", + "windows" ] - pruneopts = "" revision = "13d03a9a82fba647c21a0ef8fba44a795d0f0835" [[projects]] - digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" name = "golang.org/x/text" packages = [ "collate", @@ -751,34 +615,28 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable", + "unicode/rangetable" ] - pruneopts = "" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" - digest = "1:55a681cb66f28755765fa5fa5104cbd8dc85c55c02d206f9f89566451e3fe1aa" name = "golang.org/x/time" packages = ["rate"] - pruneopts = "" revision = "fbb02b2291d28baffd63558aa44b4b56f178d650" [[projects]] - digest = "1:2ad38d79865e33dde6157b7048debd6e7d47e0709df7b5e11bb888168e316908" name = "google.golang.org/api" packages = [ "dns/v1", "gensupport", "googleapi", - "googleapi/internal/uritemplates", + "googleapi/internal/uritemplates" ] - pruneopts = "" revision = "a0ff90edab763c86aa88f2b1eb4f3301b82f6336" [[projects]] - digest = "1:41e2b7e287117f6136f75286d48072ecf781ba54823ffeb2098e152e7dc45ef6" name = "google.golang.org/appengine" packages = [ ".", @@ -790,24 +648,20 @@ "internal/modules", "internal/remote_api", "internal/urlfetch", - "urlfetch", + "urlfetch" ] - pruneopts = "" revision = "4f7eeb5305a4ba1966344836ba4af9996b7b4e05" [[projects]] branch = "master" - digest = "1:e43f1cb3f488a0c2be85939c2a594636f60b442a12a196c778bd2d6c9aca3df7" name = "google.golang.org/genproto" packages = [ "googleapis/api/annotations", - "googleapis/rpc/status", + "googleapis/rpc/status" ] - pruneopts = "" revision = "11092d34479b07829b72e10713b159248caf5dad" [[projects]] - digest = "1:ca75b3775a5d4e5d1fb48f57ef0865b4aaa8b3f00e6b52be68db991c4594e0a7" name = "google.golang.org/grpc" packages = [ ".", @@ -836,31 +690,25 @@ "resolver/passthrough", "stats", "status", - "tap", + "tap" ] - pruneopts = "" revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" version = "v1.14.0" [[projects]] - digest = "1:e5d1fb981765b6f7513f793a3fcaac7158408cca77f75f7311ac82cc88e9c445" name = "gopkg.in/inf.v0" packages = ["."] - pruneopts = "" revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" version = "v0.9.0" [[projects]] - digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2" name = "gopkg.in/yaml.v2" packages = ["."] - pruneopts = "" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [[projects]] branch = "release-1.0" - digest = "1:bc43af6616d8ca12a7b8e806874387f0f1e181c08f547e9cd77f6cbac8cefd86" name = "istio.io/api" packages = [ "authentication/v1alpha1", @@ -868,13 +716,11 @@ "mixer/v1", "mixer/v1/config/client", "networking/v1alpha3", - "rbac/v1alpha1", + "rbac/v1alpha1" ] - pruneopts = "" revision = "76349c53b87f03f1e610b3aa3843dba3c38138d7" [[projects]] - digest = "1:7eb25280e1f610470bb0c43ab6c91573cfc78672a58542106b9b71705581429a" name = "istio.io/istio" packages = [ "pilot/pkg/config/kube/crd", @@ -883,14 +729,12 @@ "pilot/pkg/serviceregistry/kube", "pkg/cache", "pkg/kube", - "pkg/log", + "pkg/log" ] - pruneopts = "" revision = "42773aacced474d97159902d20579a25b1f98106" version = "1.0.1" [[projects]] - digest = "1:f420c8548c93242d8e5dcfa5b34e0243883b4e660f65076e869daafac877144d" name = "k8s.io/api" packages = [ "admissionregistration/v1alpha1", @@ -921,28 +765,24 @@ "settings/v1alpha1", "storage/v1", "storage/v1alpha1", - "storage/v1beta1", + "storage/v1beta1" ] - pruneopts = "" revision = "072894a440bdee3a891dea811fe42902311cd2a3" version = "kubernetes-1.11.0" [[projects]] - digest = "1:66d1421ecff35bc48ee0b11a3f891f3af6f775ed6bb1d3e0deeaba221bf42490" name = "k8s.io/apiextensions-apiserver" packages = [ "pkg/apis/apiextensions", "pkg/apis/apiextensions/v1beta1", "pkg/client/clientset/clientset", "pkg/client/clientset/clientset/scheme", - "pkg/client/clientset/clientset/typed/apiextensions/v1beta1", + "pkg/client/clientset/clientset/typed/apiextensions/v1beta1" ] - pruneopts = "" revision = "8e7f43002fec5394a8d96ebca781aa9d4b37aaef" version = "kubernetes-1.10.4" [[projects]] - digest = "1:b6b2fb7b4da1ac973b64534ace2299a02504f16bc7820cb48edb8ca4077183e1" name = "k8s.io/apimachinery" packages = [ "pkg/api/errors", @@ -985,14 +825,12 @@ "pkg/version", "pkg/watch", "third_party/forked/golang/json", - "third_party/forked/golang/reflect", + "third_party/forked/golang/reflect" ] - pruneopts = "" revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae" version = "kubernetes-1.11.0" [[projects]] - digest = "1:d04779a8de7d5465e0463bd986506348de5e89677c74777f695d3145a7a8d15e" name = "k8s.io/client-go" packages = [ "discovery", @@ -1090,92 +928,20 @@ "util/homedir", "util/integer", "util/jsonpath", - "util/retry", + "util/retry" ] - pruneopts = "" revision = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65" version = "v8.0.0" [[projects]] branch = "master" - digest = "1:526095379da1098c3f191a0008cc59c9bf9927492e63da7689e5de424219c162" name = "k8s.io/kube-openapi" packages = ["pkg/util/proto"] - pruneopts = "" revision = "d8ea2fe547a448256204cfc68dfee7b26c720acb" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - input-imports = [ - "cloud.google.com/go/compute/metadata", - "github.com/Azure/azure-sdk-for-go/arm/dns", - "github.com/Azure/go-autorest/autorest", - "github.com/Azure/go-autorest/autorest/adal", - "github.com/Azure/go-autorest/autorest/azure", - "github.com/Azure/go-autorest/autorest/to", - "github.com/alecthomas/kingpin", - "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests", - "github.com/aliyun/alibaba-cloud-sdk-go/services/alidns", - "github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz", - "github.com/aws/aws-sdk-go/aws", - "github.com/aws/aws-sdk-go/aws/credentials/stscreds", - "github.com/aws/aws-sdk-go/aws/request", - "github.com/aws/aws-sdk-go/aws/session", - "github.com/aws/aws-sdk-go/service/route53", - "github.com/aws/aws-sdk-go/service/servicediscovery", - "github.com/cloudflare/cloudflare-go", - "github.com/coreos/etcd/clientv3", - "github.com/denverdino/aliyungo/metadata", - "github.com/digitalocean/godo", - "github.com/digitalocean/godo/context", - "github.com/dnsimple/dnsimple-go/dnsimple", - "github.com/exoscale/egoscale", - "github.com/ffledgling/pdns-go", - "github.com/gophercloud/gophercloud", - "github.com/gophercloud/gophercloud/openstack", - "github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets", - "github.com/gophercloud/gophercloud/openstack/dns/v2/zones", - "github.com/gophercloud/gophercloud/pagination", - "github.com/infobloxopen/infoblox-go-client", - "github.com/kubernetes/repo-infra/verify/boilerplate/test", - "github.com/linki/instrumented_http", - "github.com/linode/linodego", - "github.com/miekg/dns", - "github.com/nesv/go-dynect/dynect", - "github.com/oracle/oci-go-sdk/common", - "github.com/oracle/oci-go-sdk/dns", - "github.com/pkg/errors", - "github.com/prometheus/client_golang/prometheus", - "github.com/prometheus/client_golang/prometheus/promhttp", - "github.com/sirupsen/logrus", - "github.com/stretchr/testify/assert", - "github.com/stretchr/testify/mock", - "github.com/stretchr/testify/require", - "github.com/stretchr/testify/suite", - "golang.org/x/net/context", - "golang.org/x/oauth2", - "golang.org/x/oauth2/google", - "google.golang.org/api/dns/v1", - "google.golang.org/api/googleapi", - "gopkg.in/yaml.v2", - "istio.io/api/networking/v1alpha3", - "istio.io/istio/pilot/pkg/config/kube/crd", - "istio.io/istio/pilot/pkg/model", - "k8s.io/api/core/v1", - "k8s.io/api/extensions/v1beta1", - "k8s.io/apimachinery/pkg/api/errors", - "k8s.io/apimachinery/pkg/apis/meta/v1", - "k8s.io/apimachinery/pkg/labels", - "k8s.io/apimachinery/pkg/runtime", - "k8s.io/apimachinery/pkg/runtime/schema", - "k8s.io/apimachinery/pkg/runtime/serializer", - "k8s.io/client-go/kubernetes", - "k8s.io/client-go/kubernetes/fake", - "k8s.io/client-go/plugin/pkg/client/auth", - "k8s.io/client-go/rest", - "k8s.io/client-go/rest/fake", - "k8s.io/client-go/tools/clientcmd", - ] + inputs-digest = "e4a3503a3672ad47f8e8f73bc26322fd1a01e2887675a444a87fee626f42da42" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 328d11f42..88f0c65ca 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -115,3 +115,7 @@ ignored = ["github.com/kubernetes/repo-infra/kazel"] [[constraint]] name = "github.com/miekg/dns" version = "1.0.8" + +[[constraint]] + name = "github.com/google/go-cmp" + version = "0.2.0" diff --git a/plan/plan.go b/plan/plan.go index 21bf5b677..22f39b9f2 100644 --- a/plan/plan.go +++ b/plan/plan.go @@ -19,6 +19,7 @@ package plan import ( "strings" + "github.com/google/go-cmp/cmp" "github.com/kubernetes-incubator/external-dns/endpoint" ) @@ -100,7 +101,7 @@ func (t planTable) getUpdates() (updateNew []*endpoint.Endpoint, updateOld []*en if row.current != nil && len(row.candidates) > 0 { //dns name is taken update := t.resolver.ResolveUpdate(row.current, row.candidates) // compare "update" to "current" to figure out if actual update is required - if shouldUpdateTTL(update, row.current) || targetChanged(update, row.current) { + if shouldUpdateTTL(update, row.current) || targetChanged(update, row.current) || shouldUpdateProviderSpecific(update, row.current) { inheritOwner(row.current, update) updateNew = append(updateNew, update) updateOld = append(updateOld, row.current) @@ -180,6 +181,10 @@ func shouldUpdateTTL(desired, current *endpoint.Endpoint) bool { return desired.RecordTTL != current.RecordTTL } +func shouldUpdateProviderSpecific(desired, current *endpoint.Endpoint) bool { + return !cmp.Equal(desired.ProviderSpecific, current.ProviderSpecific) +} + // filterRecordsForPlan removes records that are not relevant to the planner. // Currently this just removes TXT records to prevent them from being // deleted erroneously by the planner (only the TXT registry should do this.) diff --git a/plan/plan_test.go b/plan/plan_test.go index e36b343a6..ca2b3ac1a 100644 --- a/plan/plan_test.go +++ b/plan/plan_test.go @@ -27,15 +27,17 @@ import ( type PlanTestSuite struct { suite.Suite - fooV1Cname *endpoint.Endpoint - fooV2Cname *endpoint.Endpoint - fooV2TXT *endpoint.Endpoint - fooV2CnameNoLabel *endpoint.Endpoint - fooV3CnameSameResource *endpoint.Endpoint - fooA5 *endpoint.Endpoint - bar127A *endpoint.Endpoint - bar127AWithTTL *endpoint.Endpoint - bar192A *endpoint.Endpoint + fooV1Cname *endpoint.Endpoint + fooV2Cname *endpoint.Endpoint + fooV2TXT *endpoint.Endpoint + fooV2CnameNoLabel *endpoint.Endpoint + fooV3CnameSameResource *endpoint.Endpoint + fooA5 *endpoint.Endpoint + bar127A *endpoint.Endpoint + bar127AWithTTL *endpoint.Endpoint + bar127AWithProviderSpecificTrue *endpoint.Endpoint + bar127AWithProviderSpecificFalse *endpoint.Endpoint + bar192A *endpoint.Endpoint } func (suite *PlanTestSuite) SetupTest() { @@ -100,6 +102,34 @@ func (suite *PlanTestSuite) SetupTest() { endpoint.ResourceLabelKey: "ingress/default/bar-127", }, } + suite.bar127AWithProviderSpecificTrue = &endpoint.Endpoint{ + DNSName: "bar", + Targets: endpoint.Targets{"127.0.0.1"}, + RecordType: "A", + Labels: map[string]string{ + endpoint.ResourceLabelKey: "ingress/default/bar-127", + }, + ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied", + Value: "true", + }, + }, + } + suite.bar127AWithProviderSpecificFalse = &endpoint.Endpoint{ + DNSName: "bar", + Targets: endpoint.Targets{"127.0.0.1"}, + RecordType: "A", + Labels: map[string]string{ + endpoint.ResourceLabelKey: "ingress/default/bar-127", + }, + ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied", + Value: "false", + }, + }, + } suite.bar192A = &endpoint.Endpoint{ DNSName: "bar", Targets: endpoint.Targets{"192.168.0.1"}, @@ -108,6 +138,7 @@ func (suite *PlanTestSuite) SetupTest() { endpoint.ResourceLabelKey: "ingress/default/bar-192", }, } + } func (suite *PlanTestSuite) TestSyncFirstRound() { @@ -194,6 +225,27 @@ func (suite *PlanTestSuite) TestSyncSecondRoundWithTTLChange() { validateEntries(suite.T(), changes.Delete, expectedDelete) } +func (suite *PlanTestSuite) TestSyncSecondRoundWithProviderSpecificChange() { + current := []*endpoint.Endpoint{suite.bar127AWithProviderSpecificTrue} + desired := []*endpoint.Endpoint{suite.bar127AWithProviderSpecificFalse} + expectedCreate := []*endpoint.Endpoint{} + expectedUpdateOld := []*endpoint.Endpoint{suite.bar127AWithProviderSpecificTrue} + expectedUpdateNew := []*endpoint.Endpoint{suite.bar127AWithProviderSpecificFalse} + expectedDelete := []*endpoint.Endpoint{} + + p := &Plan{ + Policies: []Policy{&SyncPolicy{}}, + Current: current, + Desired: desired, + } + + changes := p.Calculate().Changes + validateEntries(suite.T(), changes.Create, expectedCreate) + validateEntries(suite.T(), changes.UpdateNew, expectedUpdateNew) + validateEntries(suite.T(), changes.UpdateOld, expectedUpdateOld) + validateEntries(suite.T(), changes.Delete, expectedDelete) +} + func (suite *PlanTestSuite) TestSyncSecondRoundWithOwnerInherited() { current := []*endpoint.Endpoint{suite.fooV1Cname} desired := []*endpoint.Endpoint{suite.fooV2Cname} @@ -354,6 +406,7 @@ func (suite *PlanTestSuite) TestDuplicatedEndpointsForSameResourceReplace() { //TODO: remove once multiple-target per endpoint is supported func (suite *PlanTestSuite) TestDuplicatedEndpointsForSameResourceRetain() { + current := []*endpoint.Endpoint{suite.fooV1Cname, suite.bar192A} desired := []*endpoint.Endpoint{suite.fooV1Cname, suite.fooV3CnameSameResource} expectedCreate := []*endpoint.Endpoint{} diff --git a/provider/cloudflare.go b/provider/cloudflare.go index ffb6bf81c..3594c1d5f 100644 --- a/provider/cloudflare.go +++ b/provider/cloudflare.go @@ -165,7 +165,7 @@ func (p *CloudFlareProvider) Records() ([]*endpoint.Endpoint, error) { for _, r := range records { if supportedRecordType(r.Type) { - endpoints = append(endpoints, endpoint.NewEndpointWithTTL(r.Name, r.Type, endpoint.TTL(r.TTL), r.Content)) + endpoints = append(endpoints, endpoint.NewEndpointWithTTL(r.Name, r.Type, endpoint.TTL(r.TTL), r.Content).WithProviderSpecific(source.CloudflareProxiedKey, strconv.FormatBool(r.Proxied))) } } } From 18b343efdd815fec066e6dffceba28f4acb401a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nick=20J=C3=BCttner?= Date: Thu, 24 Jan 2019 11:38:47 +0100 Subject: [PATCH 3/4] Update Gopkg.toml --- Gopkg.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gopkg.toml b/Gopkg.toml index c4112b411..4e99abd9e 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -120,6 +120,6 @@ ignored = ["github.com/kubernetes/repo-infra/kazel"] name = "github.com/google/go-cmp" version = "0.2.0" -[constraint]] +[[constraint]] name = "github.com/sanyu/dynectsoap" - branch = "master" \ No newline at end of file + branch = "master" From a8b127ad237d6fa6d5b84cd037d69d510ba6815c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nick=20J=C3=BCttner?= Date: Thu, 24 Jan 2019 11:48:42 +0100 Subject: [PATCH 4/4] Update Gopkg.toml