You've already forked ddns-updater
Refactor: Moved all under internal.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
FEAT: Directadmin provider is now working
This commit is contained in:
30
README.md
30
README.md
@@ -12,7 +12,7 @@ This simple updater do the job, and send notifications, if change happen.
|
||||
|
||||
Before run, you need configure this environment variables.
|
||||
|
||||
- `CLOUDFLARE_DNS_TO_CHECK` - (required) dns records that will be automatically checked and modified based on the current public IP address. Multiple entries are separated by commas. For example: `domain.com,sub1.domain.com,sub2.domain.com`
|
||||
- `DNS_NAMES` - (required) dns records that will be automatically checked and modified based on the current public IP address. Multiple entries are separated by commas. For example: `domain.com,sub1.domain.com,sub2.domain.com`
|
||||
- `CLOUDFLARE_API_KEY` - (required) your cloudflare api key, with access rights to edit selected domains. See: [https://developers.cloudflare.com/fundamentals/api/get-started/create-token/](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/)
|
||||
- `CLOUDFLARE_ZONE` - (required) zone name with domain you want to check. See: [https://developers.cloudflare.com/fundamentals/get-started/concepts/accounts-and-zones/#zones](https://developers.cloudflare.com/fundamentals/get-started/concepts/accounts-and-zones/#zones)
|
||||
- `ON_CHANGE_COMMENT` - (optional) in the event that the ip address of the dns record changes, this comment will be added to the record
|
||||
@@ -31,7 +31,7 @@ Request body example:
|
||||
"new_ip": "xxx.xxx.xxx.xxx",
|
||||
"checked_at": "2023-05-04T17:39:42.942850354+02:00",
|
||||
"resolver_tag": "ifconfig.me",
|
||||
"domain": "my.domain.com"
|
||||
"domain": "my.domain.com",
|
||||
"token": "a-webhook-token"
|
||||
}
|
||||
```
|
||||
@@ -58,24 +58,42 @@ go install github.com/mkelcik/cloudflare-ddns-update
|
||||
CLOUDFLARE_DNS_TO_CHECK="domain.com" CLOUDFLARE_API_KEY="my_key" CLOUDFLARE_ZONE="domain.com" cloudflare-ddns-update
|
||||
```
|
||||
|
||||
### Via `docker-compose`
|
||||
### Via `docker-compose for Cloudflare`
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
cf-dns-updater:
|
||||
image: mkelcik/cloudflare-ddns-update:latest
|
||||
image: hub.cybercinch.nz/cybercinch/ddns-update:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- CLOUDFLARE_DNS_TO_CHECK=my.testdomain.com,your.testdomain.com
|
||||
- CLOUDFLARE_API_KEY=your_cloudflare_api_key
|
||||
- DNS_NAMES=my.testdomain.com,your.testdomain.com
|
||||
- NOTIFIERS=webhook@http://localhost/cloudflare-updated-notification
|
||||
- CLOUDFLARE_ZONE=testdomain.com
|
||||
- ON_CHANGE_COMMENT="automatically updated"
|
||||
- CHECK_INTERVAL_SECONDS=300
|
||||
# Optional if your webhook receiver requires a token for verification
|
||||
# - WEBHOOK_TOKEN="SomeSup3rs3cureT0k3n"
|
||||
```
|
||||
|
||||
### Via `docker-compose for DirectAdmin`
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
cf-dns-updater:
|
||||
image: hub.cybercinch.nz/cybercinch/ddns-update:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DNS_PROVIDER=directadmin
|
||||
- DA_USER=some-directadmin-username
|
||||
- DA_KEY=your-directadmin-password-or-login-key
|
||||
- DA_URL=https://your.daserver.com:2222
|
||||
- DNS_NAMES=my.testdomain.com,your.testdomain.com
|
||||
- NOTIFIERS=webhook@http://localhost/cloudflare-updated-notification
|
||||
- CHECK_INTERVAL_SECONDS=300
|
||||
# Optional if your webhook receiver requires a token for verification
|
||||
# - WEBHOOK_TOKEN="SomeSup3rs3cureT0k3n"
|
||||
```
|
||||
|
||||
### Via `docker run`
|
||||
```shell
|
||||
docker run -e CLOUDFLARE_DNS_TO_CHECK=my.testdomain.com,your.testdomain.com -e CLOUDFLARE_API_KEY=your_cloudflare_api_key -e CLOUDFLARE_ZONE=testdomain.com -e ON_CHANGE_COMMENT="automatically updated" -e CHECK_INTERVAL_SECONDS=300 mkelcik/cloudflare-ddns-update:latest
|
||||
|
||||
10
go.mod
10
go.mod
@@ -1,18 +1,20 @@
|
||||
module github.com/mkelcik/cloudflare-ddns-update
|
||||
module hub.cybercinch.nz/cybercinch/ddns-update
|
||||
|
||||
|
||||
go 1.22
|
||||
|
||||
toolchain go1.22.1
|
||||
|
||||
require github.com/cloudflare/cloudflare-go v0.83.0
|
||||
require (
|
||||
github.com/cloudflare/cloudflare-go v0.83.0
|
||||
github.com/levelzerotechnology/directadmin-go v0.0.0-20240302013738-63b7793ebfd3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/levelzerotechnology/directadmin-go v0.0.0-20240302013738-63b7793ebfd3 // indirect
|
||||
github.com/mehrdadep/dex v1.0.2 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
|
||||
14
go.sum
14
go.sum
@@ -4,11 +4,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
@@ -18,16 +20,20 @@ github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXc
|
||||
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/levelzerotechnology/directadmin-go v0.0.0-20240302013738-63b7793ebfd3 h1:6kGC8EpZlYTvNI2ABYX87bBtgzfPrtZV8CKqLtSvyek=
|
||||
github.com/levelzerotechnology/directadmin-go v0.0.0-20240302013738-63b7793ebfd3/go.mod h1:FJ/EtEMwe3k2ABVYLXmE/K+H8cHVpVaSgihVT2XbSkc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mehrdadep/dex v1.0.2 h1:4rUs5xbcODC107BM6cICsfMF3qBAEqKWoZaqXClMvoo=
|
||||
github.com/mehrdadep/dex v1.0.2/go.mod h1:Vg+AUvtXkTFfNTYtQiY+NTvV3Bvyz7oiT0asmU4z440=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
|
||||
@@ -12,11 +12,13 @@ const (
|
||||
defaultCheckInterval = 5 * 60
|
||||
envKeyDnsToCheck = "DNS_NAMES"
|
||||
envKeyPublicIpResolverTag = "PUBLIC_IP_RESOLVER"
|
||||
envKeyDNSProviderTag = "DNS_PROVIDER"
|
||||
envKeyPublicDNSServer = "PUBLIC_DNS_SERVER"
|
||||
envKeyCloudflareApiKey = "CLOUDFLARE_API_KEY"
|
||||
envKeyCloudflareZone = "CLOUDFLARE_ZONE"
|
||||
envKeyDirectadminUser = "DA_USER"
|
||||
envKeyDirectadminKey = "DA_LOGIN_KEY"
|
||||
envKeyDirectadminUrl = "DA_LOGIN_URL"
|
||||
envKeyDirectadminKey = "DA_KEY"
|
||||
envKeyDirectadminUrl = "DA_URL"
|
||||
envKeyOnChangeComment = "ON_CHANGE_COMMENT"
|
||||
envKeyCheckIntervalSeconds = "CHECK_INTERVAL_SECONDS"
|
||||
envKeyNotifiers = "NOTIFIERS"
|
||||
@@ -25,6 +27,7 @@ const (
|
||||
type Config struct {
|
||||
DnsRecordsToCheck []string
|
||||
PublicIpResolverTag string
|
||||
PublicDNSServer string
|
||||
DNSProviderTag string
|
||||
DirectadminUsername string
|
||||
DirectadminKey string
|
||||
@@ -32,7 +35,7 @@ type Config struct {
|
||||
ApiToken string
|
||||
WebhookToken string
|
||||
CloudflareZone string
|
||||
OnChangeComment string
|
||||
CloudflareOnChangeComment string
|
||||
Notifiers []string
|
||||
CheckInterval time.Duration
|
||||
}
|
||||
@@ -44,21 +47,17 @@ func (c Config) Validate() error {
|
||||
return fmt.Errorf("empty api token env key %s", envKeyCloudflareApiKey)
|
||||
}
|
||||
|
||||
// if c.CloudflareZone == "" {
|
||||
// return fmt.Errorf("empty zone in env key %s", envKeyCloudflareZone)
|
||||
// }
|
||||
|
||||
case "directadmin":
|
||||
if c.DirectadminUrl == "" {
|
||||
return fmt.Errorf("empty DirectAdmin URL env key %s", envKeyDirectadminUrl)
|
||||
}
|
||||
|
||||
if c.DirectadminUsername == "" {
|
||||
return fmt.Errorf("empty Username in env key %s", envKeyDirectadminUser)
|
||||
return fmt.Errorf("empty DirectAdmin Username in env key %s", envKeyDirectadminUser)
|
||||
}
|
||||
|
||||
if c.DirectadminKey == "" {
|
||||
return fmt.Errorf("empty Login Key in env key %s", envKeyDirectadminKey)
|
||||
return fmt.Errorf("empty DirectAdmin Login Key in env key %s", envKeyDirectadminKey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,15 +77,25 @@ func NewConfig() Config {
|
||||
|
||||
return Config{
|
||||
DnsRecordsToCheck: parseCommaDelimited(os.Getenv(envKeyDnsToCheck)),
|
||||
PublicIpResolverTag: os.Getenv(envKeyPublicIpResolverTag),
|
||||
DNSProviderTag: getEnvDefault(envKeyDNSProviderTag, "cloudflare"),
|
||||
PublicDNSServer: getEnvDefault(envKeyPublicDNSServer, "1.1.1.1"),
|
||||
PublicIpResolverTag: getEnvDefault(envKeyPublicIpResolverTag, "icanhazip"),
|
||||
ApiToken: os.Getenv(envKeyCloudflareApiKey),
|
||||
CloudflareZone: os.Getenv(envKeyCloudflareZone),
|
||||
CloudflareOnChangeComment: os.Getenv(envKeyOnChangeComment),
|
||||
DirectadminUsername: os.Getenv(envKeyDirectadminUser),
|
||||
DirectadminKey: os.Getenv(envKeyDirectadminKey),
|
||||
DirectadminUrl: os.Getenv(envKeyDirectadminUrl),
|
||||
CloudflareZone: os.Getenv(envKeyCloudflareZone),
|
||||
OnChangeComment: os.Getenv(envKeyOnChangeComment),
|
||||
Notifiers: parseCommaDelimited(os.Getenv(envKeyNotifiers)),
|
||||
CheckInterval: time.Duration(checkInterval) * time.Second,
|
||||
WebhookToken: os.Getenv("WEBHOOK_TOKEN"),
|
||||
}
|
||||
}
|
||||
|
||||
func getEnvDefault(key, fallback string) string {
|
||||
value, exists := os.LookupEnv(key)
|
||||
if !exists {
|
||||
value = fallback
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestConfig_Validate(t *testing.T) {
|
||||
PublicIpResolverTag: tt.fields.PublicIpResolverTag,
|
||||
ApiToken: tt.fields.ApiToken,
|
||||
CloudflareZone: tt.fields.CloudflareZone,
|
||||
OnChangeComment: tt.fields.OnChangeComment,
|
||||
CloudflareOnChangeComment: tt.fields.OnChangeComment,
|
||||
CheckInterval: tt.fields.CheckInterval,
|
||||
}
|
||||
if err := c.Validate(); (err != nil) != tt.wantErr {
|
||||
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
)
|
||||
|
||||
type DNSProvider interface {
|
||||
UpdateRecord(hostname string, ip string, old_ip string) error
|
||||
UpdateRecord(hostname string, ip string) error
|
||||
FetchRecord(hostname string) (string, error)
|
||||
}
|
||||
|
||||
type DomainParts struct {
|
||||
@@ -16,8 +17,15 @@ type DomainParts struct {
|
||||
func GetDomainParts(hostname string) *DomainParts {
|
||||
data := arrayToSlice(strings.Split(hostname, "."))
|
||||
|
||||
if len(data) <= 2 {
|
||||
// This might be the actual root domain
|
||||
out := DomainParts{Name: strings.Join(data[0:], "."), Domain: strings.Join(data[0:], ".")}
|
||||
return &out
|
||||
} else {
|
||||
// This is a subdomain
|
||||
out := DomainParts{Name: data[0], Domain: strings.Join(data[1:], ".")}
|
||||
return &out
|
||||
}
|
||||
}
|
||||
|
||||
func arrayToSlice(array []string) []string {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/cloudflare/cloudflare-go"
|
||||
"github.com/mkelcik/cloudflare-ddns-update/internal"
|
||||
"hub.cybercinch.nz/cybercinch/ddns-update/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -18,7 +18,7 @@ type CloudflareProvider struct {
|
||||
Config internal.Config
|
||||
}
|
||||
|
||||
func (d *CloudflareProvider) UpdateRecord(hostname string, ip string, old_ip string) error {
|
||||
func (d *CloudflareProvider) UpdateRecord(hostname string, ip string) error {
|
||||
// old_ip is not required for Cloudflare updates
|
||||
domain_parts := GetDomainParts(hostname)
|
||||
zoneId := d.FindZoneIdByName(domain_parts.Domain)
|
||||
@@ -33,8 +33,8 @@ func (d *CloudflareProvider) UpdateRecord(hostname string, ip string, old_ip str
|
||||
Content: ip,
|
||||
}
|
||||
|
||||
if d.Config.OnChangeComment != "" {
|
||||
update.Comment = &d.Config.OnChangeComment
|
||||
if d.Config.CloudflareOnChangeComment != "" {
|
||||
update.Comment = &d.Config.CloudflareOnChangeComment
|
||||
}
|
||||
|
||||
_, err = d.Client.UpdateDNSRecord(d.Context, cloudflare.ZoneIdentifier(zoneId), update)
|
||||
@@ -44,6 +44,13 @@ func (d *CloudflareProvider) UpdateRecord(hostname string, ip string, old_ip str
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *CloudflareProvider) FetchRecord(hostname string) (string, error) {
|
||||
domain_parts := GetDomainParts(hostname)
|
||||
zoneId := d.FindZoneIdByName(domain_parts.Domain)
|
||||
dnsRecord, err := d.GetDnsRecord(hostname, zoneId)
|
||||
return dnsRecord[0].Content, err
|
||||
}
|
||||
|
||||
func (d *CloudflareProvider) NewClient(api_token string) {
|
||||
api, err := cloudflare.NewWithAPIToken(api_token)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,10 +2,12 @@ package dns_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/levelzerotechnology/directadmin-go"
|
||||
"github.com/mkelcik/cloudflare-ddns-update/internal"
|
||||
"hub.cybercinch.nz/cybercinch/ddns-update/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -18,20 +20,54 @@ type Directadmin struct {
|
||||
Config internal.Config
|
||||
}
|
||||
|
||||
func (d *Directadmin) UpdateRecord(hostname string, ip string, old_ip string) error {
|
||||
type ListDNSRecordsParams struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (d *Directadmin) FetchRecord(hostname string) (string, error) {
|
||||
dnsRecord, err := d.GetDnsRecord(hostname)
|
||||
if err != nil {
|
||||
log.Fatal("unable to retrieve DNS record")
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dnsRecord[0].Value, nil
|
||||
}
|
||||
|
||||
func (d *Directadmin) UpdateRecord(hostname string, ip string) error {
|
||||
|
||||
result := GetDomainParts(hostname)
|
||||
current_record, _ := d.GetDnsRecord(hostname)
|
||||
|
||||
a := directadmin.DNSRecord{Name: result.Name, Ttl: 300, Type: "A", Value: old_ip}
|
||||
b := directadmin.DNSRecord{Name: result.Name, Ttl: 300, Type: "A", Value: ip}
|
||||
// Create an updated record for the new ip
|
||||
new_record := directadmin.DNSRecord{Name: current_record[0].Name, Ttl: current_record[0].Ttl, Type: current_record[0].Type, Value: ip}
|
||||
|
||||
err := d.Client.UpdateDNSRecord(result.Domain, a, b)
|
||||
err := d.Client.UpdateDNSRecord(result.Domain, current_record[0], new_record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Directadmin) GetDnsRecord(hostname string) ([]directadmin.DNSRecord, error) {
|
||||
|
||||
domainParts := GetDomainParts(hostname)
|
||||
dnsRecords, err := d.Client.GetDNSRecords(domainParts.Domain)
|
||||
var slice []directadmin.DNSRecord
|
||||
|
||||
for _, dnsRecord := range dnsRecords {
|
||||
if domainParts.Name == dnsRecord.Name {
|
||||
slice = append(slice, dnsRecord)
|
||||
}
|
||||
}
|
||||
|
||||
if len(slice) == 0 {
|
||||
return nil, fmt.Errorf("unable to find DNS record for %s", hostname)
|
||||
}
|
||||
|
||||
return slice, err
|
||||
}
|
||||
|
||||
func (d *Directadmin) NewClient(server_url string, username string, key string) {
|
||||
api, err := directadmin.New(server_url, 5*time.Second, false, false)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package internal
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseCommaDelimited(data string) []string {
|
||||
out := make([]string, 0, strings.Count(data, ",")+1)
|
||||
|
||||
20
main.go
20
main.go
@@ -8,11 +8,10 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/mkelcik/cloudflare-ddns-update/internal"
|
||||
"github.com/mkelcik/cloudflare-ddns-update/internal/dns_providers"
|
||||
"github.com/mkelcik/cloudflare-ddns-update/internal/dns_resolver"
|
||||
"github.com/mkelcik/cloudflare-ddns-update/notifications"
|
||||
"github.com/mkelcik/cloudflare-ddns-update/public_resolvers"
|
||||
"hub.cybercinch.nz/cybercinch/ddns-update/internal"
|
||||
"hub.cybercinch.nz/cybercinch/ddns-update/internal/dns_providers"
|
||||
"hub.cybercinch.nz/cybercinch/ddns-update/internal/notifications"
|
||||
"hub.cybercinch.nz/cybercinch/ddns-update/internal/public_resolvers"
|
||||
)
|
||||
|
||||
type PublicIpResolver interface {
|
||||
@@ -75,15 +74,18 @@ func main() {
|
||||
}
|
||||
|
||||
for _, dnsRecord := range config.DnsRecordsToCheck {
|
||||
current_dns_record := dns_resolver.ResolveHostname(dnsRecord, "1.1.1.1")
|
||||
current_dns_record, err := dnsProvider.FetchRecord(dnsRecord)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to fetch DNS record: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("Checking record `%s` with current value `%s` ...", dnsRecord, current_dns_record.String())
|
||||
if currentPublicIP.String() == current_dns_record.String() {
|
||||
log.Printf("Checking record `%s` with current value `%s` ...", dnsRecord, current_dns_record)
|
||||
if currentPublicIP.String() == current_dns_record {
|
||||
log.Println("OK")
|
||||
continue // no update needed
|
||||
}
|
||||
|
||||
if err := dnsProvider.UpdateRecord(dnsRecord, currentPublicIP.String(), current_dns_record.String()); err != nil {
|
||||
if err := dnsProvider.UpdateRecord(dnsRecord, currentPublicIP.String()); err != nil {
|
||||
log.Printf("error updating dns record: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user