Skip to content

Commit 9f84877

Browse files
authored
auto create domain records for Cloudflare provider, fix #167 (#168)
* create record if it doesn't exist * auto create record for cloudflare provider * remove resolver * remove custom error
1 parent 001bb15 commit 9f84877

File tree

4 files changed

+84
-32
lines changed

4 files changed

+84
-32
lines changed

internal/handler/handler.go

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,17 @@ func (handler *Handler) updateDNS(domain *settings.Domain, ip string) error {
8080
hostname = domain.DomainName
8181
}
8282

83-
lastIP, err := utils.ResolveDNS(hostname, handler.Configuration.Resolver, handler.Configuration.IPType)
84-
if err != nil {
85-
log.Error(err)
86-
continue
83+
if err := handler.dnsProvider.UpdateIP(domain.DomainName, subdomainName, ip); err != nil {
84+
return err
8785
}
8886

89-
//check against the current known IP, if no change, skip update
90-
if ip == lastIP {
91-
log.Infof("IP is the same as cached one (%s). Skip update.", ip)
92-
} else {
93-
if err := handler.dnsProvider.UpdateIP(domain.DomainName, subdomainName, ip); err != nil {
94-
return err
95-
}
87+
successMessage := fmt.Sprintf("%s.%s", subdomainName, domain.DomainName)
88+
handler.notificationManager.Send(successMessage, ip)
9689

97-
successMessage := fmt.Sprintf("%s.%s", subdomainName, domain.DomainName)
98-
handler.notificationManager.Send(successMessage, ip)
99-
100-
// execute webhook when it is enabled
101-
if handler.Configuration.Webhook.Enabled {
102-
if err := lib.GetWebhook(handler.Configuration).Execute(hostname, ip); err != nil {
103-
return err
104-
}
90+
// execute webhook when it is enabled
91+
if handler.Configuration.Webhook.Enabled {
92+
if err := lib.GetWebhook(handler.Configuration).Execute(hostname, ip); err != nil {
93+
return err
10594
}
10695
}
10796
}

internal/provider/alidns/alidns_handler.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,20 @@ func (provider *DNSProvider) UpdateIP(domainName, subdomainName, ip string) erro
2323
log.Infof("%s.%s - Start to update record IP...", subdomainName, domainName)
2424
records := provider.aliDNS.GetDomainRecords(domainName, subdomainName)
2525
if len(records) == 0 {
26-
log.Errorf("Cannot get subdomain %s from AliDNS.", subdomainName)
27-
return fmt.Errorf("cannot get subdomain %s from AliDNS", subdomainName)
26+
log.Errorf("Cannot get subdomain [%s] from AliDNS.", subdomainName)
27+
return fmt.Errorf("cannot get subdomain [%s] from AliDNS", subdomainName)
2828
}
2929

30-
records[0].Value = ip
31-
if err := provider.aliDNS.UpdateDomainRecord(records[0]); err != nil {
32-
log.Errorf("Failed to update IP for subdomain: %s", subdomainName)
33-
return fmt.Errorf("failed to update IP for subdomain: %s", subdomainName)
30+
if records[0].Value != ip {
31+
records[0].Value = ip
32+
if err := provider.aliDNS.UpdateDomainRecord(records[0]); err != nil {
33+
return fmt.Errorf("failed to update IP for subdomain: %s", subdomainName)
34+
}
35+
36+
log.Infof("IP updated for subdomain: %s", subdomainName)
37+
} else {
38+
log.Debugf("IP not changed for subdomain: %s", subdomainName)
3439
}
3540

36-
log.Infof("IP updated for subdomain:%s", subdomainName)
3741
return nil
3842
}

internal/provider/cloudflare/cloudflare_handler.go

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,34 @@ func (provider *DNSProvider) UpdateIP(domainName, subdomainName, ip string) erro
7676
zoneID := provider.getZone(domainName)
7777
if zoneID != "" {
7878
records := provider.getDNSRecords(zoneID)
79+
matched := false
7980

8081
// update records
8182
for _, rec := range records {
83+
rec := rec
8284
if !recordTracked(provider.getCurrentDomain(domainName), &rec) {
8385
log.Debug("Skipping record:", rec.Name)
8486
continue
8587
}
86-
if rec.IP != ip {
87-
log.Infof("IP mismatch: Current(%+v) vs Cloudflare(%+v)", ip, rec.IP)
88-
provider.updateRecord(rec, ip)
89-
} else {
90-
log.Infof("Record OK: %+v - %+v", rec.Name, rec.IP)
88+
89+
if strings.Contains(rec.Name, subdomainName) {
90+
if rec.IP != ip {
91+
log.Infof("IP mismatch: Current(%+v) vs Cloudflare(%+v)", ip, rec.IP)
92+
provider.updateRecord(rec, ip)
93+
} else {
94+
log.Infof("Record OK: %+v - %+v", rec.Name, rec.IP)
95+
}
96+
97+
matched = true
98+
}
99+
}
100+
101+
if !matched {
102+
log.Debugf("Record %s not found, will create it.", subdomainName)
103+
if err := provider.createRecord(zoneID, domainName, subdomainName, ip); err != nil {
104+
return err
91105
}
106+
log.Infof("Record [%s] created with IP address: %s", subdomainName, ip)
92107
}
93108
} else {
94109
log.Errorf("Failed to find zone for domain: %s", domainName)
@@ -100,6 +115,7 @@ func (provider *DNSProvider) UpdateIP(domainName, subdomainName, ip string) erro
100115

101116
func (provider *DNSProvider) getCurrentDomain(domainName string) *settings.Domain {
102117
for _, domain := range provider.configuration.Domains {
118+
domain := domain
103119
if domain.DomainName == domainName {
104120
return &domain
105121
}
@@ -210,6 +226,49 @@ func (provider *DNSProvider) getDNSRecords(zoneID string) []DNSRecord {
210226
return r.Records
211227
}
212228

229+
func (provider *DNSProvider) createRecord(zoneID, domain, subDomain, ip string) error {
230+
newRecord := DNSRecord{
231+
Type: utils.IPTypeA,
232+
Name: fmt.Sprintf("%s.%s", subDomain, domain),
233+
IP: ip,
234+
TTL: 1,
235+
}
236+
237+
content, err := json.Marshal(newRecord)
238+
if err != nil {
239+
log.Errorf("Encoder error: %+v", err)
240+
return err
241+
}
242+
243+
req, client := provider.newRequest("POST", fmt.Sprintf("/zones/%s/dns_records", zoneID), bytes.NewBuffer(content))
244+
resp, err := client.Do(req)
245+
if err != nil {
246+
log.Error("Request error:", err)
247+
return err
248+
}
249+
250+
defer resp.Body.Close()
251+
body, err := ioutil.ReadAll(resp.Body)
252+
if err != nil {
253+
log.Errorf("Failed to read request body: %+v", err)
254+
return err
255+
}
256+
257+
var r DNSRecordUpdateResponse
258+
err = json.Unmarshal(body, &r)
259+
if err != nil {
260+
log.Errorf("Decoder error: %+v", err)
261+
return err
262+
}
263+
264+
if !r.Success {
265+
log.Infof("Response failed: %+v", string(body))
266+
return fmt.Errorf("failed to create record: %+v", string(body))
267+
}
268+
269+
return nil
270+
}
271+
213272
// Update DNS A Record with new IP.
214273
func (provider *DNSProvider) updateRecord(record DNSRecord, newIP string) string {
215274

@@ -228,6 +287,7 @@ func (provider *DNSProvider) updateRecord(record DNSRecord, newIP string) string
228287
return ""
229288
}
230289

290+
defer resp.Body.Close()
231291
body, _ := ioutil.ReadAll(resp.Body)
232292
err = json.Unmarshal(body, &r)
233293
if err != nil {

internal/provider/dnspod/dnspod_provider.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ func (provider *DNSProvider) UpdateIP(domainName, subdomainName, ip string) erro
4040

4141
subdomainID, currentIP := provider.getSubDomain(domainID, subdomainName)
4242
if subdomainID == "" || currentIP == "" {
43-
log.Errorf("Domain or subdomain not configured yet. domain: %s.%s subDomainID: %s ip: %s", subdomainName, domainName, subdomainID, ip)
4443
return fmt.Errorf("domain or subdomain not configured yet. domain: %s.%s subDomainID: %s ip: %s", subdomainName, domainName, subdomainID, ip)
4544
}
4645

0 commit comments

Comments
 (0)