main
Raw Download raw file
  1package cf
  2
  3import (
  4	"context"
  5	"fmt"
  6
  7	"github.com/cloudflare/cloudflare-go"
  8)
  9
 10// CF handles interactions with the Cloudflare API.
 11type CF struct {
 12	api          *cloudflare.API
 13	zone         *cloudflare.ResourceContainer // ZoneID Container
 14	record       *cloudflare.DNSRecord
 15	recordExists bool
 16}
 17
 18// New creates a new instance of CF with the provided API token.
 19func New(
 20	zoneName string,
 21	subdomainName string,
 22	apiToken string,
 23) (*CF, error) {
 24
 25	api, err := cloudflare.NewWithAPIToken(apiToken)
 26	if err != nil {
 27		return nil, err
 28	}
 29
 30	cf := &CF{
 31		api: api,
 32	}
 33
 34	id, err := cf.api.ZoneIDByName(zoneName)
 35	if err != nil {
 36		return nil, fmt.Errorf(
 37			"failed to lookup zone id name=%s: %w",
 38			zoneName,
 39			err)
 40	}
 41	cf.zone = cloudflare.ZoneIdentifier(id)
 42
 43	records, resultInfo, err := cf.api.ListDNSRecords(
 44		context.Background(),
 45		cf.zone,
 46		cloudflare.ListDNSRecordsParams{
 47			Type: "A",
 48			Name: subdomainName,
 49		})
 50	if err != nil {
 51		err = fmt.Errorf(
 52			"failed to lookup dns record name=%s: %w",
 53			subdomainName,
 54			err)
 55		return nil, err
 56	}
 57
 58	if len(records) == 0 || resultInfo.Count == 0 {
 59		cf.record = &cloudflare.DNSRecord{
 60			Type: "A",
 61			Name: subdomainName,
 62			TTL:  60,
 63		}
 64		cf.recordExists = false
 65		return cf, nil
 66	}
 67
 68	cf.record = &records[0]
 69	cf.recordExists = true
 70	return cf, nil
 71}
 72
 73func (cf *CF) IP() string {
 74	if cf.zone == nil {
 75		return "unknown: lookup failed, no zone"
 76	}
 77	if cf.record == nil || cf.record.Name == "" {
 78		return "unknown: lookup failed, no record"
 79	}
 80	if !cf.recordExists {
 81		return "unset"
 82	}
 83	return cf.record.Content
 84}
 85
 86func (cf *CF) SetIP(ip string) error {
 87
 88	if cf.zone == nil {
 89		return fmt.Errorf("zone must be set")
 90	}
 91	if cf.record == nil || cf.record.Name == "" {
 92		return fmt.Errorf("dns record must be set")
 93	}
 94
 95	if !cf.recordExists {
 96		record, err := cf.api.CreateDNSRecord(
 97			context.Background(),
 98			cf.zone,
 99			cloudflare.CreateDNSRecordParams{
100				Type:    cf.record.Type,
101				Name:    cf.record.Name,
102				Content: ip,
103				TTL:     cf.record.TTL,
104			})
105		if err != nil {
106			return fmt.Errorf("failed to create dns record name=%s: %w",
107				cf.record.Name,
108				err)
109		}
110		cf.record = &record
111		cf.recordExists = true
112		return nil
113	}
114
115	record, err := cf.api.UpdateDNSRecord(
116		context.Background(),
117		cf.zone,
118		cloudflare.UpdateDNSRecordParams{
119			Type:    cf.record.Type,
120			Name:    cf.record.Name,
121			Content: ip,
122			ID:      cf.record.ID,
123			TTL:     cf.record.TTL,
124		})
125	if err != nil {
126		return fmt.Errorf("failed to update dns record name=%s: %w",
127			cf.record.Name,
128			err)
129	}
130	cf.record = &record
131	return nil
132}