domain_records.go raw

   1  package linodego
   2  
   3  import (
   4  	"context"
   5  	"encoding/json"
   6  	"time"
   7  
   8  	"github.com/linode/linodego/internal/parseabletime"
   9  )
  10  
  11  // DomainRecord represents a DomainRecord object
  12  type DomainRecord struct {
  13  	ID       int              `json:"id"`
  14  	Type     DomainRecordType `json:"type"`
  15  	Name     string           `json:"name"`
  16  	Target   string           `json:"target"`
  17  	Priority int              `json:"priority"`
  18  	Weight   int              `json:"weight"`
  19  	Port     int              `json:"port"`
  20  	Service  *string          `json:"service"`
  21  	Protocol *string          `json:"protocol"`
  22  	TTLSec   int              `json:"ttl_sec"`
  23  	Tag      *string          `json:"tag"`
  24  	Created  *time.Time       `json:"-"`
  25  	Updated  *time.Time       `json:"-"`
  26  }
  27  
  28  // DomainRecordCreateOptions fields are those accepted by CreateDomainRecord
  29  type DomainRecordCreateOptions struct {
  30  	Type     DomainRecordType `json:"type"`
  31  	Name     string           `json:"name"`
  32  	Target   string           `json:"target"`
  33  	Priority *int             `json:"priority,omitempty"`
  34  	Weight   *int             `json:"weight,omitempty"`
  35  	Port     *int             `json:"port,omitempty"`
  36  	Service  *string          `json:"service,omitempty"`
  37  	Protocol *string          `json:"protocol,omitempty"`
  38  	TTLSec   int              `json:"ttl_sec,omitempty"` // 0 is not accepted by Linode, so can be omitted
  39  	Tag      *string          `json:"tag,omitempty"`
  40  }
  41  
  42  // DomainRecordUpdateOptions fields are those accepted by UpdateDomainRecord
  43  type DomainRecordUpdateOptions struct {
  44  	Type     DomainRecordType `json:"type,omitempty"`
  45  	Name     string           `json:"name,omitempty"`
  46  	Target   string           `json:"target,omitempty"`
  47  	Priority *int             `json:"priority,omitempty"` // 0 is valid, so omit only nil values
  48  	Weight   *int             `json:"weight,omitempty"`   // 0 is valid, so omit only nil values
  49  	Port     *int             `json:"port,omitempty"`     // 0 is valid to spec, so omit only nil values
  50  	Service  *string          `json:"service,omitempty"`
  51  	Protocol *string          `json:"protocol,omitempty"`
  52  	TTLSec   int              `json:"ttl_sec,omitempty"` // 0 is not accepted by Linode, so can be omitted
  53  	Tag      *string          `json:"tag,omitempty"`
  54  }
  55  
  56  // DomainRecordType constants start with RecordType and include Linode API Domain Record Types
  57  type DomainRecordType string
  58  
  59  // DomainRecordType constants are the DNS record types a DomainRecord can assign
  60  const (
  61  	RecordTypeA     DomainRecordType = "A"
  62  	RecordTypeAAAA  DomainRecordType = "AAAA"
  63  	RecordTypeNS    DomainRecordType = "NS"
  64  	RecordTypeMX    DomainRecordType = "MX"
  65  	RecordTypeCNAME DomainRecordType = "CNAME"
  66  	RecordTypeTXT   DomainRecordType = "TXT"
  67  	RecordTypeSRV   DomainRecordType = "SRV"
  68  	RecordTypePTR   DomainRecordType = "PTR"
  69  	RecordTypeCAA   DomainRecordType = "CAA"
  70  )
  71  
  72  // UnmarshalJSON for DomainRecord responses
  73  func (d *DomainRecord) UnmarshalJSON(b []byte) error {
  74  	type Mask DomainRecord
  75  
  76  	p := struct {
  77  		*Mask
  78  
  79  		Created *parseabletime.ParseableTime `json:"created"`
  80  		Updated *parseabletime.ParseableTime `json:"updated"`
  81  	}{
  82  		Mask: (*Mask)(d),
  83  	}
  84  
  85  	if err := json.Unmarshal(b, &p); err != nil {
  86  		return err
  87  	}
  88  
  89  	d.Created = (*time.Time)(p.Created)
  90  	d.Updated = (*time.Time)(p.Updated)
  91  
  92  	return nil
  93  }
  94  
  95  // GetUpdateOptions converts a DomainRecord to DomainRecordUpdateOptions for use in UpdateDomainRecord
  96  func (d DomainRecord) GetUpdateOptions() (du DomainRecordUpdateOptions) {
  97  	du.Type = d.Type
  98  	du.Name = d.Name
  99  	du.Target = d.Target
 100  	du.Priority = copyInt(&d.Priority)
 101  	du.Weight = copyInt(&d.Weight)
 102  	du.Port = copyInt(&d.Port)
 103  	du.Service = copyString(d.Service)
 104  	du.Protocol = copyString(d.Protocol)
 105  	du.TTLSec = d.TTLSec
 106  	du.Tag = copyString(d.Tag)
 107  
 108  	return du
 109  }
 110  
 111  // ListDomainRecords lists DomainRecords
 112  func (c *Client) ListDomainRecords(ctx context.Context, domainID int, opts *ListOptions) ([]DomainRecord, error) {
 113  	return getPaginatedResults[DomainRecord](ctx, c, formatAPIPath("domains/%d/records", domainID), opts)
 114  }
 115  
 116  // GetDomainRecord gets the domainrecord with the provided ID
 117  func (c *Client) GetDomainRecord(ctx context.Context, domainID int, recordID int) (*DomainRecord, error) {
 118  	e := formatAPIPath("domains/%d/records/%d", domainID, recordID)
 119  	return doGETRequest[DomainRecord](ctx, c, e)
 120  }
 121  
 122  // CreateDomainRecord creates a DomainRecord
 123  func (c *Client) CreateDomainRecord(ctx context.Context, domainID int, opts DomainRecordCreateOptions) (*DomainRecord, error) {
 124  	e := formatAPIPath("domains/%d/records", domainID)
 125  	return doPOSTRequest[DomainRecord](ctx, c, e, opts)
 126  }
 127  
 128  // UpdateDomainRecord updates the DomainRecord with the specified id
 129  func (c *Client) UpdateDomainRecord(ctx context.Context, domainID int, recordID int, opts DomainRecordUpdateOptions) (*DomainRecord, error) {
 130  	e := formatAPIPath("domains/%d/records/%d", domainID, recordID)
 131  	return doPUTRequest[DomainRecord](ctx, c, e, opts)
 132  }
 133  
 134  // DeleteDomainRecord deletes the DomainRecord with the specified id
 135  func (c *Client) DeleteDomainRecord(ctx context.Context, domainID int, recordID int) error {
 136  	e := formatAPIPath("domains/%d/records/%d", domainID, recordID)
 137  	return doDELETERequest(ctx, c, e)
 138  }
 139