main
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}