diff --git a/docs/_includes/matrix.html b/docs/_includes/matrix.html
index ca30b946a..3e6de9fe7 100644
--- a/docs/_includes/matrix.html
+++ b/docs/_includes/matrix.html
@@ -627,7 +627,9 @@
|
- |
+
+
+ |
|
@@ -1819,8 +1821,8 @@
|
-
-
+ |
+
|
diff --git a/providers/linode/api.go b/providers/linode/api.go
index 59f72c093..496a64537 100644
--- a/providers/linode/api.go
+++ b/providers/linode/api.go
@@ -221,20 +221,21 @@ type domainRecord struct {
Port uint16 `json:"port"`
Service string `json:"service"`
Protocol string `json:"protocol"`
+ Tag string `json:"tag"`
TTLSec uint32 `json:"ttl_sec"`
}
type recordEditRequest struct {
Type string `json:"type,omitempty"`
- Name string `json:"name,omitempty"`
- Target string `json:"target,omitempty"`
+ Name string `json:"name"`
+ Target string `json:"target"`
Priority int `json:"priority,omitempty"`
Weight int `json:"weight,omitempty"`
Port int `json:"port,omitempty"`
Service string `json:"service,omitempty"`
Protocol string `json:"protocol,omitempty"`
- // Documented as field `ttl` in the documentation, but in reality `ttl_sec` should be used
- TTL int `json:"ttl_sec,omitempty"`
+ Tag string `json:"tag,omitempty"`
+ TTL int `json:"ttl_sec,omitempty"`
}
type errorResponse struct {
diff --git a/providers/linode/linodeProvider.go b/providers/linode/linodeProvider.go
index 9dcd0ea85..a7aad227b 100644
--- a/providers/linode/linodeProvider.go
+++ b/providers/linode/linodeProvider.go
@@ -86,7 +86,8 @@ func NewLinode(m map[string]string, metadata json.RawMessage) (providers.DNSServ
}
var features = providers.DocumentationNotes{
- providers.CanGetZones: providers.Unimplemented(),
+ providers.CanGetZones: providers.Can(),
+ providers.CanUseCAA: providers.Can("Linode doesn't support changing the CAA flag"),
providers.DocDualHost: providers.Cannot(),
providers.DocOfficiallySupported: providers.Cannot(),
}
@@ -107,10 +108,17 @@ func (api *linodeProvider) GetNameservers(domain string) ([]*models.Nameserver,
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
func (api *linodeProvider) GetZoneRecords(domain string) (models.Records, error) {
- return nil, fmt.Errorf("not implemented")
- // This enables the get-zones subcommand.
- // Implement this by extracting the code from GetDomainCorrections into
- // a single function. For most providers this should be relatively easy.
+ if api.domainIndex == nil {
+ if err := api.fetchDomainList(); err != nil {
+ return nil, err
+ }
+ }
+ domainID, ok := api.domainIndex[domain]
+ if !ok {
+ return nil, fmt.Errorf("'%s' not a zone in Linode account", domain)
+ }
+
+ return api.getRecordsForDomain(domainID, domain)
}
// GetDomainCorrections returns the corrections for a domain.
@@ -132,29 +140,11 @@ func (api *linodeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
return nil, fmt.Errorf("'%s' not a zone in Linode account", dc.Name)
}
- records, err := api.getRecords(domainID)
+ existingRecords, err := api.getRecordsForDomain(domainID, dc.Name)
if err != nil {
return nil, err
}
- existingRecords := make([]*models.RecordConfig, len(records), len(records)+len(defaultNameServerNames))
- for i := range records {
- existingRecords[i] = toRc(dc, &records[i])
- }
-
- // Linode always has read-only NS servers, but these are not mentioned in the API response
- // https://github.com/linode/manager/blob/edd99dc4e1be5ab8190f243c3dbf8b830716255e/src/constants.js#L184
- for _, name := range defaultNameServerNames {
- rc := &models.RecordConfig{
- Type: "NS",
- Original: &domainRecord{},
- }
- rc.SetLabelFromFQDN(dc.Name, dc.Name)
- rc.SetTarget(name)
-
- existingRecords = append(existingRecords, rc)
- }
-
// Normalize
models.PostProcessRecords(existingRecords)
@@ -235,25 +225,54 @@ func (api *linodeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
return corrections, nil
}
-func toRc(dc *models.DomainConfig, r *domainRecord) *models.RecordConfig {
+func (api *linodeProvider) getRecordsForDomain(domainID int, domain string) (models.Records, error) {
+ records, err := api.getRecords(domainID)
+ if err != nil {
+ return nil, err
+ }
+
+ existingRecords := make([]*models.RecordConfig, len(records), len(records)+len(defaultNameServerNames))
+ for i := range records {
+ existingRecords[i] = toRc(domain, &records[i])
+ }
+
+ // Linode always has read-only NS servers, but these are not mentioned in the API response
+ // https://github.com/linode/manager/blob/edd99dc4e1be5ab8190f243c3dbf8b830716255e/src/constants.js#L184
+ for _, name := range defaultNameServerNames {
+ rc := &models.RecordConfig{
+ Type: "NS",
+ Original: &domainRecord{},
+ }
+ rc.SetLabelFromFQDN(domain, domain)
+ rc.SetTarget(name)
+
+ existingRecords = append(existingRecords, rc)
+ }
+
+ return existingRecords, nil
+}
+
+func toRc(domain string, r *domainRecord) *models.RecordConfig {
rc := &models.RecordConfig{
Type: r.Type,
TTL: r.TTLSec,
MxPreference: r.Priority,
SrvPriority: r.Priority,
SrvWeight: r.Weight,
- SrvPort: uint16(r.Port),
+ SrvPort: r.Port,
+ CaaTag: r.Tag,
Original: r,
}
- rc.SetLabel(r.Name, dc.Name)
+ rc.SetLabel(r.Name, domain)
switch rtype := r.Type; rtype { // #rtype_variations
- case "TXT":
- rc.SetTargetTXT(r.Target)
case "CNAME", "MX", "NS", "SRV":
- rc.SetTarget(dnsutil.AddOrigin(r.Target+".", dc.Name))
- default:
+ rc.SetTarget(dnsutil.AddOrigin(r.Target+".", domain))
+ case "CAA":
+ // Linode doesn't support CAA flags and just returns the tag and value separately
rc.SetTarget(r.Target)
+ default:
+ rc.PopulateFromString(r.Type, r.Target, domain)
}
return rc
@@ -277,11 +296,16 @@ func toReq(dc *models.DomainConfig, rc *models.RecordConfig) (*recordEditRequest
// Linode uses the same property for MX and SRV priority
switch rc.Type { // #rtype_variations
- case "A", "AAAA", "NS", "PTR", "TXT", "SOA", "TLSA", "CAA":
+ case "A", "AAAA", "NS", "PTR", "TXT", "SOA", "TLSA":
// Nothing special.
case "MX":
req.Priority = int(rc.MxPreference)
req.Target = fixTarget(req.Target, dc.Name)
+
+ // Linode doesn't use "." for a null MX record, it uses an empty name
+ if req.Target == "." {
+ req.Target = ""
+ }
case "SRV":
req.Priority = int(rc.SrvPriority)
@@ -300,6 +324,8 @@ func toReq(dc *models.DomainConfig, rc *models.RecordConfig) (*recordEditRequest
req.Name = ""
case "CNAME":
req.Target = fixTarget(req.Target, dc.Name)
+ case "CAA":
+ req.Tag = rc.CaaTag
default:
return nil, fmt.Errorf("linode.toReq rtype %q unimplemented", rc.Type)
}
@@ -329,5 +355,3 @@ func fixTTL(ttl uint32) uint32 {
return allowedTTLValues[0]
}
-
-// that have not been updated for a new RR type.
|