mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
Allow setting Cloudflare proxying by annotation
This commit is contained in:
parent
5fea7534b3
commit
e0e7a9defd
@ -14,7 +14,11 @@ Here is typical example of [CRD API type](https://github.com/kubernetes-incubato
|
|||||||
```go
|
```go
|
||||||
type TTL int64
|
type TTL int64
|
||||||
type Targets []string
|
type Targets []string
|
||||||
type ProviderSpecific map[string]string
|
type ProviderSpecificProperty struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
type ProviderSpecific []ProviderSpecificProperty
|
||||||
|
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
// The hostname of the DNS record
|
// The hostname of the DNS record
|
||||||
|
@ -33,7 +33,14 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
type: object
|
type: object
|
||||||
providerSpecific:
|
providerSpecific:
|
||||||
type: object
|
items:
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
recordTTL:
|
recordTTL:
|
||||||
format: int64
|
format: int64
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -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 nginx.yaml
|
||||||
$ kubectl delete service -f externaldns.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.
|
||||||
|
@ -109,8 +109,14 @@ func (t Targets) IsLess(o Targets) bool {
|
|||||||
return false
|
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
|
// 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
|
// Endpoint is a high-level way of a connection between a service and an IP
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
@ -160,10 +166,21 @@ func (e *Endpoint) WithProviderSpecific(key, value string) *Endpoint {
|
|||||||
if e.ProviderSpecific == nil {
|
if e.ProviderSpecific == nil {
|
||||||
e.ProviderSpecific = ProviderSpecific{}
|
e.ProviderSpecific = ProviderSpecific{}
|
||||||
}
|
}
|
||||||
e.ProviderSpecific[key] = value
|
|
||||||
|
e.ProviderSpecific = append(e.ProviderSpecific, ProviderSpecificProperty{Name: key, Value: value})
|
||||||
return e
|
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 {
|
func (e *Endpoint) String() string {
|
||||||
return fmt.Sprintf("%s %d IN %s %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Targets, e.ProviderSpecific)
|
return fmt.Sprintf("%s %d IN %s %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Targets, e.ProviderSpecific)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package testutils
|
package testutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/external-dns/endpoint"
|
"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 &&
|
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.OwnerLabelKey] == b.Labels[endpoint.OwnerLabelKey] && a.RecordTTL == b.RecordTTL &&
|
||||||
a.Labels[endpoint.ResourceLabelKey] == b.Labels[endpoint.ResourceLabelKey] &&
|
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
|
// 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"])
|
SameEndpoints(a["UpdateOld"], b["UpdateOld"]) && SameEndpoints(a["UpdateNew"], b["UpdateNew"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// SameMap verifies that two maps contain the same string/string key/value pairs
|
// SameProverSpecific verifies that two maps contain the same string/string key/value pairs
|
||||||
func SameMap(a, b map[string]string) bool {
|
func SameProverSpecific(a, b endpoint.ProviderSpecific) bool {
|
||||||
if len(a) != len(b) {
|
return reflect.DeepEqual(a, b)
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range a {
|
|
||||||
if v != b[k] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
@ -56,9 +56,11 @@ func ExampleSameEndpoints() {
|
|||||||
RecordTTL: endpoint.TTL(60),
|
RecordTTL: endpoint.TTL(60),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
DNSName: "example.org",
|
DNSName: "example.org",
|
||||||
Targets: endpoint.Targets{"load-balancer.org"},
|
Targets: endpoint.Targets{"load-balancer.org"},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{"foo": "bar"},
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
|
endpoint.ProviderSpecificProperty{Name: "foo", Value: "bar"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
sort.Sort(byAllFields(eps))
|
sort.Sort(byAllFields(eps))
|
||||||
@ -66,11 +68,11 @@ func ExampleSameEndpoints() {
|
|||||||
fmt.Println(ep)
|
fmt.Println(ep)
|
||||||
}
|
}
|
||||||
// Output:
|
// Output:
|
||||||
// abc.com 0 IN A 1.2.3.4 map[]
|
// abc.com 0 IN A 1.2.3.4 []
|
||||||
// abc.com 0 IN TXT something map[]
|
// abc.com 0 IN TXT something []
|
||||||
// bbc.com 0 IN CNAME foo.com map[]
|
// bbc.com 0 IN CNAME foo.com []
|
||||||
// cbc.com 60 IN CNAME foo.com map[]
|
// cbc.com 60 IN CNAME foo.com []
|
||||||
// example.org 0 IN load-balancer.org map[]
|
// example.org 0 IN load-balancer.org []
|
||||||
// example.org 0 IN load-balancer.org map[foo:bar]
|
// example.org 0 IN load-balancer.org [{foo bar}]
|
||||||
// example.org 0 IN TXT load-balancer.org map[]
|
// example.org 0 IN TXT load-balancer.org []
|
||||||
}
|
}
|
||||||
|
@ -371,8 +371,8 @@ func (p *AWSProvider) newChange(action string, endpoint *endpoint.Endpoint) *rou
|
|||||||
|
|
||||||
if isAWSLoadBalancer(endpoint) {
|
if isAWSLoadBalancer(endpoint) {
|
||||||
evalTargetHealth := p.evaluateTargetHealth
|
evalTargetHealth := p.evaluateTargetHealth
|
||||||
if _, ok := endpoint.ProviderSpecific[providerSpecificEvaluateTargetHealth]; ok {
|
if prop, ok := endpoint.GetProviderSpecificProperty(providerSpecificEvaluateTargetHealth); ok {
|
||||||
evalTargetHealth = endpoint.ProviderSpecific[providerSpecificEvaluateTargetHealth] == "true"
|
evalTargetHealth = prop.Value == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
change.ResourceRecordSet.Type = aws.String(route53.RRTypeA)
|
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.
|
// 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 {
|
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 {
|
for _, addr := range addrs {
|
||||||
if addr.DNSName == ep.Targets[0] {
|
if addr.DNSName == ep.Targets[0] {
|
||||||
if hostedZone := canonicalHostedZone(addr.Targets[0]); hostedZone != "" {
|
if hostedZone := canonicalHostedZone(addr.Targets[0]); hostedZone != "" {
|
||||||
|
@ -781,7 +781,10 @@ func TestAWSCreateRecordsWithALIAS(t *testing.T) {
|
|||||||
Targets: endpoint.Targets{"foo.eu-central-1.elb.amazonaws.com"},
|
Targets: endpoint.Targets{"foo.eu-central-1.elb.amazonaws.com"},
|
||||||
RecordType: endpoint.RecordTypeCNAME,
|
RecordType: endpoint.RecordTypeCNAME,
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
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", ""},
|
{"foo.example.org", endpoint.RecordTypeCNAME, "true", ""},
|
||||||
} {
|
} {
|
||||||
ep := &endpoint.Endpoint{
|
ep := &endpoint.Endpoint{
|
||||||
Targets: endpoint.Targets{tc.target},
|
Targets: endpoint.Targets{tc.target},
|
||||||
RecordType: tc.recordType,
|
RecordType: tc.recordType,
|
||||||
ProviderSpecific: map[string]string{"alias": tc.alias},
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
|
endpoint.ProviderSpecificProperty{
|
||||||
|
Name: "alias",
|
||||||
|
Value: tc.alias,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
addrs := []*endpoint.Endpoint{
|
addrs := []*endpoint.Endpoint{
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,7 @@ package provider
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
cloudflare "github.com/cloudflare/cloudflare-go"
|
cloudflare "github.com/cloudflare/cloudflare-go"
|
||||||
@ -26,6 +27,7 @@ import (
|
|||||||
|
|
||||||
"github.com/kubernetes-incubator/external-dns/endpoint"
|
"github.com/kubernetes-incubator/external-dns/endpoint"
|
||||||
"github.com/kubernetes-incubator/external-dns/plan"
|
"github.com/kubernetes-incubator/external-dns/plan"
|
||||||
|
"github.com/kubernetes-incubator/external-dns/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -93,10 +95,10 @@ func (z zoneService) DeleteDNSRecord(zoneID, recordID string) error {
|
|||||||
type CloudFlareProvider struct {
|
type CloudFlareProvider struct {
|
||||||
Client cloudFlareDNS
|
Client cloudFlareDNS
|
||||||
// only consider hosted zones managing domains ending in this suffix
|
// only consider hosted zones managing domains ending in this suffix
|
||||||
domainFilter DomainFilter
|
domainFilter DomainFilter
|
||||||
zoneIDFilter ZoneIDFilter
|
zoneIDFilter ZoneIDFilter
|
||||||
proxied bool
|
proxiedByDefault bool
|
||||||
DryRun bool
|
DryRun bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// cloudFlareChange differentiates between ChangActions
|
// cloudFlareChange differentiates between ChangActions
|
||||||
@ -106,7 +108,7 @@ type cloudFlareChange struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewCloudFlareProvider initializes a new CloudFlare DNS based Provider.
|
// 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
|
// 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"))
|
config, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -114,11 +116,11 @@ func NewCloudFlareProvider(domainFilter DomainFilter, zoneIDFilter ZoneIDFilter,
|
|||||||
}
|
}
|
||||||
provider := &CloudFlareProvider{
|
provider := &CloudFlareProvider{
|
||||||
//Client: config,
|
//Client: config,
|
||||||
Client: zoneService{config},
|
Client: zoneService{config},
|
||||||
domainFilter: domainFilter,
|
domainFilter: domainFilter,
|
||||||
zoneIDFilter: zoneIDFilter,
|
zoneIDFilter: zoneIDFilter,
|
||||||
proxied: proxied,
|
proxiedByDefault: proxiedByDefault,
|
||||||
DryRun: dryRun,
|
DryRun: dryRun,
|
||||||
}
|
}
|
||||||
return provider, nil
|
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.
|
// ApplyChanges applies a given set of changes in a given zone.
|
||||||
func (p *CloudFlareProvider) ApplyChanges(changes *plan.Changes) error {
|
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 := 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(cloudFlareCreate, changes.Create, proxiedByDefault)...)
|
||||||
combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareUpdate, changes.UpdateNew, p.proxied)...)
|
combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareUpdate, changes.UpdateNew, proxiedByDefault)...)
|
||||||
combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareDelete, changes.Delete, p.proxied)...)
|
combinedChanges = append(combinedChanges, newCloudFlareChanges(cloudFlareDelete, changes.Delete, proxiedByDefault)...)
|
||||||
|
|
||||||
return p.submitChanges(combinedChanges)
|
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.
|
// 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))
|
changes := make([]*cloudFlareChange, 0, len(endpoints))
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
changes = append(changes, newCloudFlareChange(action, endpoint, proxied))
|
changes = append(changes, newCloudFlareChange(action, endpoint, proxiedByDefault))
|
||||||
}
|
}
|
||||||
|
|
||||||
return changes
|
return changes
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCloudFlareChange(action string, endpoint *endpoint.Endpoint, proxied bool) *cloudFlareChange {
|
func newCloudFlareChange(action string, endpoint *endpoint.Endpoint, proxiedByDefault bool) *cloudFlareChange {
|
||||||
ttl := defaultCloudFlareRecordTTL
|
ttl := defaultCloudFlareRecordTTL
|
||||||
if proxied && (cloudFlareTypeNotSupported[endpoint.RecordType] || strings.Contains(endpoint.DNSName, "*")) {
|
proxied := shouldBeProxied(endpoint, proxiedByDefault)
|
||||||
proxied = false
|
|
||||||
}
|
|
||||||
if endpoint.RecordTTL.IsConfigured() {
|
if endpoint.RecordTTL.IsConfigured() {
|
||||||
ttl = int(endpoint.RecordTTL)
|
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
|
||||||
|
}
|
||||||
|
@ -368,6 +368,36 @@ func TestNewCloudFlareChangeNoProxied(t *testing.T) {
|
|||||||
assert.False(t, change.ResourceRecordSet.Proxied)
|
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) {
|
func TestNewCloudFlareChangeProxiable(t *testing.T) {
|
||||||
var cloudFlareTypes = []struct {
|
var cloudFlareTypes = []struct {
|
||||||
recordType string
|
recordType string
|
||||||
|
@ -232,7 +232,6 @@ func endpointsFromIngress(ing *v1beta1.Ingress) []*endpoint.Endpoint {
|
|||||||
for _, hostname := range hostnameList {
|
for _, hostname := range hostnameList {
|
||||||
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...)
|
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpoints
|
return endpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
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), ",")
|
hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",")
|
||||||
for _, hostname := range hostnameList {
|
for _, hostname := range hostnameList {
|
||||||
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets)...)
|
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets, providerSpecific)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpoints, nil
|
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 {
|
func (sc *serviceSource) endpoints(svc *v1.Service, nodeTargets endpoint.Targets) []*endpoint.Endpoint {
|
||||||
var endpoints []*endpoint.Endpoint
|
var endpoints []*endpoint.Endpoint
|
||||||
|
|
||||||
|
providerSpecific := getProviderSpecificAnnotations(svc.Annotations)
|
||||||
hostnameList := getHostnamesFromAnnotations(svc.Annotations)
|
hostnameList := getHostnamesFromAnnotations(svc.Annotations)
|
||||||
for _, hostname := range hostnameList {
|
for _, hostname := range hostnameList {
|
||||||
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets)...)
|
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, nodeTargets, providerSpecific)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpoints
|
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, ".")
|
hostname = strings.TrimSuffix(hostname, ".")
|
||||||
ttl, err := getTTLFromAnnotations(svc.Annotations)
|
ttl, err := getTTLFromAnnotations(svc.Annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -296,19 +298,21 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, nod
|
|||||||
}
|
}
|
||||||
|
|
||||||
epA := &endpoint.Endpoint{
|
epA := &endpoint.Endpoint{
|
||||||
RecordTTL: ttl,
|
RecordTTL: ttl,
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
Labels: endpoint.NewLabels(),
|
Labels: endpoint.NewLabels(),
|
||||||
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
|
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
|
||||||
DNSName: hostname,
|
DNSName: hostname,
|
||||||
|
ProviderSpecific: providerSpecific,
|
||||||
}
|
}
|
||||||
|
|
||||||
epCNAME := &endpoint.Endpoint{
|
epCNAME := &endpoint.Endpoint{
|
||||||
RecordTTL: ttl,
|
RecordTTL: ttl,
|
||||||
RecordType: endpoint.RecordTypeCNAME,
|
RecordType: endpoint.RecordTypeCNAME,
|
||||||
Labels: endpoint.NewLabels(),
|
Labels: endpoint.NewLabels(),
|
||||||
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
|
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
|
||||||
DNSName: hostname,
|
DNSName: hostname,
|
||||||
|
ProviderSpecific: providerSpecific,
|
||||||
}
|
}
|
||||||
|
|
||||||
var endpoints []*endpoint.Endpoint
|
var endpoints []*endpoint.Endpoint
|
||||||
|
@ -41,6 +41,12 @@ const (
|
|||||||
controllerAnnotationValue = "dns-controller"
|
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 (
|
const (
|
||||||
ttlMinimum = 1
|
ttlMinimum = 1
|
||||||
ttlMaximum = math.MaxUint32
|
ttlMaximum = math.MaxUint32
|
||||||
@ -72,7 +78,6 @@ func getHostnamesFromAnnotations(annotations map[string]string) []string {
|
|||||||
if !exists {
|
if !exists {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Split(strings.Replace(hostnameAnnotation, " ", "", -1), ",")
|
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 {
|
func getProviderSpecificAnnotations(annotations map[string]string) endpoint.ProviderSpecific {
|
||||||
if getAliasFromAnnotations(annotations) {
|
providerSpecificAnnotations := endpoint.ProviderSpecific{}
|
||||||
return map[string]string{"alias": "true"}
|
|
||||||
|
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.
|
// getTargetsFromTargetAnnotation gets endpoints from optional "target" annotation.
|
||||||
|
Loading…
Reference in New Issue
Block a user