diff --git a/go.mod b/go.mod index 9d0f227..8ee477f 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module cloudflare-ddns +module github.com/mkelcik/cloudflare-ddns-update go 1.20 diff --git a/internal/config_test.go b/internal/config_test.go new file mode 100644 index 0000000..0811ad0 --- /dev/null +++ b/internal/config_test.go @@ -0,0 +1,74 @@ +package internal + +import ( + "testing" + "time" +) + +func TestConfig_Validate(t *testing.T) { + type fields struct { + DnsRecordsToCheck []string + PublicIpResolverTag string + ApiToken string + CloudflareZone string + OnChangeComment string + CheckInterval time.Duration + } + tests := []struct { + name string + fields fields + wantErr bool + }{ + { + name: "all ok", + fields: fields{ + DnsRecordsToCheck: []string{"domain1", "domain2"}, + ApiToken: "some_api_key", + CloudflareZone: "some_zone", + }, + wantErr: false, + }, + { + name: "empty api token", + fields: fields{ + DnsRecordsToCheck: []string{"domain1", "domain2"}, + ApiToken: "", + CloudflareZone: "some_zone", + }, + wantErr: true, + }, + { + name: "empty check dns record", + fields: fields{ + DnsRecordsToCheck: []string{}, + ApiToken: "", + CloudflareZone: "some_zone", + }, + wantErr: true, + }, + { + name: "empty zone", + fields: fields{ + DnsRecordsToCheck: []string{"domain1", "domain2"}, + ApiToken: "some_api_key", + CloudflareZone: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := Config{ + DnsRecordsToCheck: tt.fields.DnsRecordsToCheck, + PublicIpResolverTag: tt.fields.PublicIpResolverTag, + ApiToken: tt.fields.ApiToken, + CloudflareZone: tt.fields.CloudflareZone, + OnChangeComment: tt.fields.OnChangeComment, + CheckInterval: tt.fields.CheckInterval, + } + if err := c.Validate(); (err != nil) != tt.wantErr { + t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/helpers.go b/internal/helpers.go index d2fa19e..e287078 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -5,7 +5,9 @@ import "strings" func parseDNSToCheck(data string) []string { out := make([]string, 0, strings.Count(data, ",")+1) for _, dns := range strings.Split(data, ",") { - out = append(out, strings.TrimSpace(dns)) + if w := strings.TrimSpace(dns); w != "" { + out = append(out, w) + } } return out } diff --git a/internal/helpers_test.go b/internal/helpers_test.go new file mode 100644 index 0000000..d13168d --- /dev/null +++ b/internal/helpers_test.go @@ -0,0 +1,83 @@ +package internal + +import ( + "reflect" + "testing" +) + +func Test_parseDNSToCheck(t *testing.T) { + type args struct { + data string + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "test parsing", + args: args{ + data: "word1,word2,", + }, + want: []string{"word1", "word2"}, + }, + { + name: "test parsing with spaces", + args: args{ + data: " word1, word2 ", + }, + want: []string{"word1", "word2"}, + }, + { + name: "test parsing with empty word", + args: args{ + data: " word1, word2 ,", + }, + want: []string{"word1", "word2"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := parseDNSToCheck(tt.args.data); !reflect.DeepEqual(got, tt.want) { + t.Errorf("parseDNSToCheck() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestContains(t *testing.T) { + type args[T comparable] struct { + haystack []T + needle T + } + type testCase[T comparable] struct { + name string + args args[T] + want bool + } + tests := []testCase[string]{ + { + name: "yes", + args: args[string]{ + haystack: []string{"w1", "w2"}, + needle: "w1", + }, + want: true, + }, + { + name: "no", + args: args[string]{ + haystack: []string{"w1", "w2"}, + needle: "w3", + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Contains(tt.args.haystack, tt.args.needle); got != tt.want { + t.Errorf("Contains() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/main.go b/main.go index 394ec15..f66eaff 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,9 @@ import ( "syscall" "time" - "cloudflare-ddns/internal" - "cloudflare-ddns/public_resolvers" "github.com/cloudflare/cloudflare-go" + "github.com/mkelcik/cloudflare-ddns-update/internal" + "github.com/mkelcik/cloudflare-ddns-update/public_resolvers" ) type PublicIpResolver interface { @@ -44,6 +44,8 @@ func main() { log.Fatal(err) } + log.Printf("Current public ip `%s`", currentPublicIP) + api, err := cloudflare.NewWithAPIToken(config.ApiToken) if err != nil { log.Fatal(err)