Skip to content

Commit

Permalink
CO-47 - Support all Cloudflare DNS record types (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
rxbn authored Feb 23, 2023
1 parent 6404214 commit 2c89fae
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 29 deletions.
11 changes: 9 additions & 2 deletions api/v1beta1/dnsrecord_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ type DNSRecordSpec struct {
// Reference to an IP object
// +optional
IPRef DNSRecordSpecIPRef `json:"ipRef,omitempty"`
// DNS record type (A, AAAA, CNAME)
// +kubebuilder:validation:Enum=A;AAAA;CNAME
// DNS record type
// +kubebuilder:default=A
// +optional
Type string `json:"type,omitempty"`
Expand All @@ -52,6 +51,14 @@ type DNSRecordSpec struct {
// +kubebuilder:default=1
// +optional
TTL int `json:"ttl,omitempty"`
// Data holds arbitrary key-value pairs used for SRV and LOC records
// +optional
Data map[string]string `json:"data,omitempty"`
// Required for MX, SRV and URI records; unused by other record types. Records with lower priorities are preferred.
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=65535
// +optional
Priority *uint16 `json:"priority,omitempty"`
// Interval to check DNSRecord
// +kubebuilder:default="5m"
// +optional
Expand Down
12 changes: 12 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 13 additions & 5 deletions config/crd/bases/cf.containeroo.ch_dnsrecords.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ spec:
content:
description: DNS record content (e.g. 127.0.0.1)
type: string
data:
additionalProperties:
type: string
description: Data holds arbitrary key-value pairs used for SRV and
LOC records
type: object
interval:
default: 5m
description: Interval to check DNSRecord
Expand All @@ -72,6 +78,12 @@ spec:
description: DNS record name (e.g. example.com)
maxLength: 255
type: string
priority:
description: Required for MX, SRV and URI records; unused by other
record types. Records with lower priorities are preferred.
maximum: 65535
minimum: 0
type: integer
proxied:
default: true
description: Whether the record is receiving the performance and security
Expand All @@ -86,11 +98,7 @@ spec:
type: integer
type:
default: A
description: DNS record type (A, AAAA, CNAME)
enum:
- A
- AAAA
- CNAME
description: DNS record type
type: string
required:
- name
Expand Down
77 changes: 56 additions & 21 deletions controllers/dnsrecord_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,6 @@ func (r *DNSRecordReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}
}

if instance.Spec.Content == "" && instance.Spec.IPRef.Name == "" {
err := r.markFailed(instance, ctx, "No content or IP reference provided")
if err != nil {
log.Error(err, "Failed to update DNSRecord status")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}

if (instance.Spec.Type == "A" || instance.Spec.Type == "AAAA") && instance.Spec.IPRef.Name != "" {
ip := &cfv1beta1.IP{}
err := r.Get(ctx, client.ObjectKey{Name: instance.Spec.IPRef.Name}, ip)
Expand Down Expand Up @@ -192,11 +183,13 @@ func (r *DNSRecordReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

if existingRecord.ID == "" {
resp, err := r.Cf.CreateDNSRecord(ctx, cloudflare.ZoneIdentifier(dnsRecordZoneId), cloudflare.CreateDNSRecordParams{
Name: instance.Spec.Name,
Type: instance.Spec.Type,
Content: instance.Spec.Content,
TTL: instance.Spec.TTL,
Proxied: instance.Spec.Proxied,
Name: instance.Spec.Name,
Type: instance.Spec.Type,
Content: instance.Spec.Content,
TTL: instance.Spec.TTL,
Proxied: instance.Spec.Proxied,
Priority: instance.Spec.Priority,
Data: instance.Spec.Data,
})
if err != nil {
err := r.markFailed(instance, ctx, err.Error())
Expand Down Expand Up @@ -225,14 +218,18 @@ func (r *DNSRecordReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
existingRecord.Type != instance.Spec.Type ||
existingRecord.Content != instance.Spec.Content ||
existingRecord.TTL != instance.Spec.TTL ||
*existingRecord.Proxied != *instance.Spec.Proxied {
*existingRecord.Proxied != *instance.Spec.Proxied ||
!comparePriority(existingRecord.Priority, instance.Spec.Priority) ||
!compareData(existingRecord.Data, instance.Spec.Data) {
err := r.Cf.UpdateDNSRecord(ctx, cloudflare.ZoneIdentifier(dnsRecordZoneId), cloudflare.UpdateDNSRecordParams{
ID: existingRecord.ID,
Name: instance.Spec.Name,
Type: instance.Spec.Type,
Content: instance.Spec.Content,
TTL: instance.Spec.TTL,
Proxied: instance.Spec.Proxied,
ID: existingRecord.ID,
Name: instance.Spec.Name,
Type: instance.Spec.Type,
Content: instance.Spec.Content,
TTL: instance.Spec.TTL,
Proxied: instance.Spec.Proxied,
Priority: instance.Spec.Priority,
Data: instance.Spec.Data,
})
if err != nil {
err := r.markFailed(instance, ctx, err.Error())
Expand Down Expand Up @@ -307,3 +304,41 @@ func (r *DNSRecordReconciler) markFailed(instance *cfv1beta1.DNSRecord, ctx cont
}
return nil
}

// comparePriority compares the priority nil safe
func comparePriority(a, b *uint16) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
return *a == *b
}

// compareData compares the data nil safe
func compareData(a interface{}, b map[string]string) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
am, ok := a.(map[string]interface{})
if !ok {
return false
}
if len(am) != len(b) {
return false
}
for k, v := range am {
vv, ok := v.(string)
if !ok {
return false
}
if vv != b[k] {
return false
}
}
return true
}
2 changes: 1 addition & 1 deletion controllers/zone_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func (r *ZoneReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
if !strings.HasSuffix(cfDnsRecord.Name, instance.Spec.Name) {
continue
}
if cfDnsRecord.Type != "A" && cfDnsRecord.Type != "AAAA" && cfDnsRecord.Type != "CNAME" {
if cfDnsRecord.Type == "TXT" && strings.HasPrefix(cfDnsRecord.Content, "_acme-challenge") {
continue
}

Expand Down

0 comments on commit 2c89fae

Please sign in to comment.