Skip to content

Commit

Permalink
[#30] - include support for SRV records
Browse files Browse the repository at this point in the history
  • Loading branch information
n3integration committed Feb 26, 2020
1 parent 257e13b commit 507b94f
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 31 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<dl>
<dt>Terraform v0.12.x</dt>
<dd>https://github.com/n3integration/terraform-godaddy/releases/tag/v1.7.0</dd>
<dd>https://github.com/n3integration/terraform-godaddy/releases/tag/v1.7.1</dd>
<dt>Terraform v0.11.x</dt>
<dd>https://github.com/n3integration/terraform-godaddy/releases/tag/v1.6.4</dd>
<dt>Terraform v0.10.x</dt>
Expand Down Expand Up @@ -55,6 +55,7 @@ types include:
* MX
* NS
* SOA
* SRV
* TXT

```terraform
Expand Down Expand Up @@ -82,6 +83,16 @@ resource "godaddy_domain_record" "gd-fancy-domain" {
priority = 1
}
record {
name = "@"
type = "SRV"
data = "host.example.com"
ttl = 3600
service = "_ldap"
protocol = "_tcp"
port = 389
}
// specify any A records associated with the domain
addresses = ["192.168.1.2", "192.168.1.3"]
Expand All @@ -101,7 +112,7 @@ fully automated imports.

## License

Copyright 2019 n3integration@gmail.com
Copyright 2020 n3integration@gmail.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
130 changes: 105 additions & 25 deletions api/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package api

import (
"errors"
"fmt"
"strings"
)
Expand Down Expand Up @@ -44,6 +45,8 @@ func (rt RecordType) String() string {
return NSType
case SOA:
return SOAType
case SRV:
return SRVType
case TXT:
return TXTType
}
Expand All @@ -53,6 +56,8 @@ func (rt RecordType) String() string {
const (
DefaultTTL = 3600
DefaultPriority = 0
DefaultWeight = 0
DefaultPort = 0

StatusActive = "ACTIVE"
StatusCancelled = "CANCELLED"
Expand All @@ -64,11 +69,12 @@ const (
MXType = "MX"
NSType = "NS"
SOAType = "SOA"
SRVType = "SRV"
TXTType = "TXT"
)

var supportedTypes = []string{
AType, AAAAType, CNameType, MXType, NSType, SOAType, TXTType,
AType, AAAAType, CNameType, MXType, NSType, SOAType, SRVType, TXTType,
}

// Domain encapsulates a domain resource
Expand All @@ -83,16 +89,19 @@ type DomainRecord struct {
Type string `json:"type,omitempty"`
Name string `json:"name"`
Data string `json:"data"`
Priority int `json:"priority,omitempty"`
Priority int `json:"priority"`
TTL int `json:"ttl"`
// Service string `json:"service"`
// Protocol string `json:"protocol"`
// Port int `json:"port"`
// Weight int `json:"weight"`
Service string `json:"service,omitempty"`
Protocol string `json:"protocol,omitempty"`
Weight int `json:"weight"`
Port *int `json:"port,omitempty"`
}

// DomainRecordOpt provides support for setting optional parameters
type DomainRecordOpt func(*DomainRecord) error

// NewDomainRecord validates and constructs a DomainRecord, if valid.
func NewDomainRecord(name, t, data string, ttl int, priority int) (*DomainRecord, error) {
func NewDomainRecord(name, t, data string, ttl int, opts ...DomainRecordOpt) (*DomainRecord, error) {
name = strings.TrimSpace(name)
data = strings.TrimSpace(data)
if err := ValidateData(t, data); err != nil {
Expand All @@ -101,52 +110,109 @@ func NewDomainRecord(name, t, data string, ttl int, priority int) (*DomainRecord

parts := strings.Split(name, ".")
if len(parts) < 1 || len(parts) > 255 {
return nil, fmt.Errorf("name must be between 1..255 octets")
return nil, errors.New("name must be between 1..255 octets")
}
for _, part := range parts {
if len(part) > 63 {
return nil, fmt.Errorf("invalid domain name. name octets should be less than 63 characters")
return nil, errors.New("invalid domain name. name octets should be less than 63 characters")
}
}

if ttl < 0 {
return nil, fmt.Errorf("ttl must be a positive value")
}
if err := ValidatePriority(priority); err != nil {
return nil, err
return nil, errors.New("ttl must be a positive value")
}
if !isSupportedType(t) {
return nil, fmt.Errorf("type must be one of: %s", supportedTypes)
}
return &DomainRecord{
Name: name,
Type: t,
Data: data,
TTL: ttl,
Priority: priority,
}, nil
dr := &DomainRecord{
Name: name,
Type: t,
Data: data,
TTL: ttl,
}
for _, opt := range opts {
if err := opt(dr); err != nil {
return nil, err
}
}
return dr, nil
}

func Priority(priority int) DomainRecordOpt {
return func(rec *DomainRecord) error {
if err := ValidatePriority(priority); err != nil {
return err
}
rec.Priority = priority
return nil
}
}

func Weight(weight int) DomainRecordOpt {
return func(rec *DomainRecord) error {
if err := ValidateWeight(weight); err != nil {
return err
}
rec.Weight = weight
return nil
}
}

func Port(port int) DomainRecordOpt {
return func(rec *DomainRecord) error {
if port == 0 {
return nil
}
if err := ValidatePort(port); err != nil {
return err
}
rec.Port = &port
return nil
}
}

func Service(service string) DomainRecordOpt {
return func(rec *DomainRecord) error {
if strings.TrimSpace(service) != "" && !strings.HasPrefix(service, "_") {
return errors.New("service must start with an underscore (e.g. _ldap)")
}
rec.Service = service
return nil
}
}

func Protocol(proto string) DomainRecordOpt {
return func(rec *DomainRecord) error {
if strings.TrimSpace(proto) != "" && !strings.HasPrefix(proto, "_") {
return errors.New("protocol must start with an underscore (e.g. _tcp)")
}
rec.Protocol = proto
return nil
}
}

// NewNSRecord constructs a nameserver record from the supplied data
func NewNSRecord(data string) (*DomainRecord, error) {
return NewDomainRecord(Ptr, NSType, data, DefaultTTL, DefaultPriority)
return NewDomainRecord(Ptr, NSType, data, DefaultTTL)
}

// NewARecord constructs a new address record from the supplied data
func NewARecord(data string) (*DomainRecord, error) {
return NewDomainRecord(Ptr, AType, data, DefaultTTL, DefaultPriority)
return NewDomainRecord(Ptr, AType, data, DefaultTTL)
}

// ValidateData performs bounds checking on a data element
func ValidateData(t, data string) error {
switch t {
case SRVType:
return nil
case TXTType:
if len(data) < 0 || len(data) > 512 {
return fmt.Errorf("TXT data must be between 0..512 characters in length")
return errors.New("TXT data must be between 0..512 characters in length")
}
default:
if len(data) < 0 || len(data) > 255 {
return fmt.Errorf("data must be between 0..255 characters in length")
return errors.New("data must be between 0..255 characters in length")
}
}
return nil
Expand All @@ -155,7 +221,21 @@ func ValidateData(t, data string) error {
// ValidatePriority performs bounds checking on priority element
func ValidatePriority(priority int) error {
if priority < 0 || priority > 65535 {
return fmt.Errorf("priority must be between 0..65535 (16 bit)")
return errors.New("priority must be between 0..65535 (16 bit)")
}
return nil
}

func ValidateWeight(weight int) error {
if weight < 0 || weight > 100 {
return errors.New("weight must be between 0..100")
}
return nil
}

func ValidatePort(port int) error {
if port < 1 || port > 65535 {
return errors.New("port must be between 1..65535")
}
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions api/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestNewDomainRecord(t *testing.T) {
}
for _, test := range criteria {
t.Run(test.Name, func(t *testing.T) {
if _, err := NewDomainRecord(test.Domain, "A", "127.0.0.1", 60, 0); err != nil {
if _, err := NewDomainRecord(test.Domain, "A", "127.0.0.1", 60); err != nil {
if !test.Negative {
t.Errorf("failed to create new domain record: %s", err)
}
Expand All @@ -34,4 +34,4 @@ func randBinaryString(n int) string {
out[i] = binRunes[rand.Intn(len(binRunes))]
}
return string(out)
}
}
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

version=1.7.0
version=1.7.1

os=$(uname -s | tr '[:upper:]' '[:lower:]')
mach=$(uname -m)
Expand Down
32 changes: 31 additions & 1 deletion plugin/terraform-godaddy/resource_dns_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const (
recData = "data"
recTTL = "ttl"
recPriority = "priority"
recWeight = "weight"
recProto = "protocol"
recService = "service"
recPort = "port"
)

type domainRecordResource struct {
Expand Down Expand Up @@ -67,7 +71,11 @@ func newDomainRecordResource(d *schema.ResourceData) (*domainRecordResource, err
t,
data[recData].(string),
data[recTTL].(int),
data[recPriority].(int))
api.Priority(data[recPriority].(int)),
api.Weight(data[recWeight].(int)),
api.Port(data[recPort].(int)),
api.Service(data[recService].(string)),
api.Protocol(data[recProto].(string)))

if err != nil {
return r, err
Expand Down Expand Up @@ -175,6 +183,24 @@ func resourceDomainRecord() *schema.Resource {
Optional: true,
Default: api.DefaultPriority,
},
recWeight: {
Type: schema.TypeInt,
Optional: true,
Default: api.DefaultWeight,
},
recService: {
Type: schema.TypeString,
Optional: true,
},
recProto: {
Type: schema.TypeString,
Optional: true,
},
recPort: {
Type: schema.TypeInt,
Optional: true,
Default: api.DefaultPort,
},
},
},
},
Expand Down Expand Up @@ -293,6 +319,10 @@ func flattenRecords(list []*api.DomainRecord) []map[string]interface{} {
recData: r.Data,
recTTL: r.TTL,
recPriority: r.Priority,
recWeight: r.Weight,
recPort: r.Port,
recService: r.Service,
recProto: r.Protocol,
}
}
return result
Expand Down

0 comments on commit 507b94f

Please sign in to comment.