Skip to content

Commit

Permalink
Merge pull request #3 from sestus/remove-hardcoded-domain
Browse files Browse the repository at this point in the history
Remove the hardcoded domain "mikemylonakis.com" - figure it out from the given subdomain instead. Fixes #1
  • Loading branch information
mikemyl authored Feb 3, 2021
2 parents 2afd8da + 3ab0ca0 commit b946c2d
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Go
name: Build and Test

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out.

idea/
.idea
1 change: 0 additions & 1 deletion .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ GoDaddy DynDns
==============

[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/sestus/godyndns/master/LICENSE)
[![Build status](https://travis-ci.com/sestus/godyndns.svg?branch=master)](https://travis-ci.com/github/sestus/godyndns)
[![Build and Test](https://github.com/sestus/godyndns/workflows/Build%20and%20Test/badge.svg)](https://github.com/sestus/godyndns/actions)


godaddy-dyndns is a simple utility that is basically a DIY dynamic DNS. It checks the current public IP against a
Expand Down
Binary file added cmd/godaddy-dyndns/godaddy-dyndns
Binary file not shown.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/Bowery/prompt v0.0.0-20190916142128-fa8279994f75 // indirect
github.com/jpillora/go-tld v1.1.1
github.com/labstack/gommon v0.3.0
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mkideal/cli v0.0.5
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/Bowery/prompt v0.0.0-20190916142128-fa8279994f75 h1:xGHheKK44eC6K0u5X
github.com/Bowery/prompt v0.0.0-20190916142128-fa8279994f75/go.mod h1:4/6eNcqZ09BZ9wLK3tZOjBA1nDj+B0728nlX5YRlSmQ=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jpillora/go-tld v1.1.1 h1:P1ZwtKDHBYYUl235R/D64cdBARfGYzEy1Hg2Ikir3FQ=
github.com/jpillora/go-tld v1.1.1/go.mod h1:kitBxOF//DR5FxYeIGw+etdiiTIq5S7bx0dwy1GUNAk=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
Expand All @@ -27,13 +29,17 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
43 changes: 38 additions & 5 deletions godyndns.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/jpillora/go-tld"
"io/ioutil"
"log"
"net"
Expand Down Expand Up @@ -46,18 +47,28 @@ func UpdateGoDaddyARecord(client *http.Client, domainName string, publicIp net.I
log.Println("Given publicIp is nll")
return errors.New("given publicIp is nll")
}
url := fmt.Sprintf("%s/mikemylonakis.com/records/A/%s", domainsPath, domainName)
domainUrl, err := constructUrl(domainName)
if err != nil {
log.Printf("Failed to update the A record as I couldn't extract the domain from %s\n", domainName)
return err
}

url := fmt.Sprintf("%s/%s.%s/records/A/%s", domainsPath, domainUrl.Domain, domainUrl.TLD, domainUrl.Subdomain)
record, _:= json.Marshal(domainUpdates{domainUpdate{publicIp.String(), 600}})
req, _ := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(record))
addHeaders(req, apiKey, secretKey)
_, err := doRequest(client, req)
_, err = doRequest(client, req)
return err

}

func GetGodaddyARecordIp(client *http.Client, domainName string, apiKey, secretKey string) (net.IP, error) {
url := fmt.Sprintf("%s/mikemylonakis.com/records/A/%s", domainsPath, domainName)
req, err := http.NewRequest(http.MethodGet, url, nil)
domainUrl, err := constructUrl(domainName)
if err != nil {
log.Printf("Failed to get A record as I couldn't extract the domain from %s\n", domainName)
return nil, err
}
targetUrl := fmt.Sprintf("%s/%s.%s/records/A/%s", domainsPath, domainUrl.Domain, domainUrl.TLD, domainUrl.Subdomain)
req, err := http.NewRequest(http.MethodGet, targetUrl, nil)
if err != nil {
log.Printf("Failed to get the record details for domain %s : %s", domainName, err)
return nil, err
Expand Down Expand Up @@ -90,6 +101,28 @@ func GetGodaddyARecordIp(client *http.Client, domainName string, apiKey, secretK
return net.ParseIP(record[0].Data), nil
}

func constructUrl(subdomain string) (*tld.URL, error) {
u, err := tld.Parse(subdomain)
if err != nil {
log.Printf("Couldn't construct domain from %s : %s", subdomain, err)
return nil, err
}
if !u.ICANN {
u, err = tld.Parse("https://" + subdomain)
if err != nil {
log.Printf("Couldn't construct domain from %s : %s", subdomain, err)
return nil, err
}
}
if len(u.Domain) == 0 || len(u.TLD) == 0 {
return nil, errors.New("Couldn't extract domain from " + subdomain)
}
if len(u.Subdomain) == 0 {
return nil, errors.New("Couldn't extract subdomain from " + subdomain)
}
return u, nil
}

func addHeaders(r *http.Request, apiKey, secretKey string) *http.Request {
r.Header.Set("Authorization", fmt.Sprintf("sso-key %s:%s", apiKey, secretKey))
r.Header.Set("accept", "application/json")
Expand Down
46 changes: 39 additions & 7 deletions godyndns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ func TestGetGodaddyARecordIp(t *testing.T) {
want net.IP
hasError bool
}{
{"Should parse the ip from the JSON", args{mockHttpClient(200, "200 OK", `[{"data":"1.1.1.1","name":"some.domain.com","ttl":600,"type":"A"}]`), "domainName", "apiKey", "secretKey"}, net.ParseIP("1.1.1.1"), false},
{"Should return nil if non valid ip is returned", args{mockHttpClient(200, "200 OK", `[{"data":"invalid","name":"some.domain.com","ttl":600,"type":"A"}]`), "domainName", "apiKey", "secretKey"}, nil, true},
{"Should return nil non 200 status code is returned", args{mockHttpClient(401, "401 Unauthorized", ``), "domainName", "apiKey", "secretKey"}, nil, true},
{"Should parse the ip from the JSON", args{mockHttpClient(200, "200 OK", `[{"data":"1.1.1.1","name":"some.domain.com","ttl":600,"type":"A"}]`), "some.domain.com", "apiKey", "secretKey"}, net.ParseIP("1.1.1.1"), false},
{"Should return nil if non valid ip is returned", args{mockHttpClient(200, "200 OK", `[{"data":"invalid","name":"some.domain.com","ttl":600,"type":"A"}]`), "some.domain.com", "apiKey", "secretKey"}, nil, true},
{"Should return nil non 200 status code is returned", args{mockHttpClient(401, "401 Unauthorized", ``), "some.domain.com", "apiKey", "secretKey"}, nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -74,9 +74,9 @@ func TestUpdateGoDaddyARecord(t *testing.T) {
args args
hasError bool
}{
{"Should return err if nil IP is given", args{mockHttpClient(0, "ignored", `[]`), "domainName", nil, "apiKey", "secretKey"}, true},
{"Should return err if non 200 http status code", args{mockHttpClient(404, "404 Bad request", `[]`), "domainName", nil, "apiKey", "secretKey"}, true},
{"Shouldn't return err if valid request", args{mockHttpClient(200, "200 OK", `ignored`), "domainName", net.ParseIP("1.1.1.1"), "apiKey", "secretKey"}, false},
{"Should return err if nil IP is given", args{mockHttpClient(0, "ignored", `[]`), "some.domain.com", nil, "apiKey", "secretKey"}, true},
{"Should return err if non 200 http status code", args{mockHttpClient(404, "404 Bad request", `[]`), "some.domain.com", nil, "apiKey", "secretKey"}, true},
{"Shouldn't return err if valid request", args{mockHttpClient(200, "200 OK", `ignored`), "some.domain.com", net.ParseIP("1.1.1.1"), "apiKey", "secretKey"}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -102,6 +102,38 @@ func Test_addHeaders(t *testing.T) {
assertEqual(t, "sso-key foo:bar", got.Header.Get("Authorization"))
}

func Test_constructUrl_AddsSchemeAndCreatesUrl(t *testing.T) {
tests := []struct {
name string
domainInput string
wantedSubDomain string
wantedDomain string
wantError bool
}{
{"Simple domain", "foo.bar.com", "foo", "bar.com", false},
{"Domain starting with https://", "https://foo.bar.com", "foo", "bar.com", false},
{"co.uk doamin", "https://foo.bar.co.uk", "foo", "bar.co.uk", false},
{"No subdomain", "nosubdomain.io", "", "", true},
{"No domain", "invalid-domain", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
url, err := constructUrl(tt.domainInput)
if err != nil {
if !tt.wantError {
t.Errorf("construnctUrl returned an error unexpectedly")
}
} else {
if tt.wantError {
t.Errorf("wanted an error but didn't get one")
}
assertEqual(t, tt.wantedDomain, url.Domain + "." + url.TLD)
assertEqual(t, tt.wantedSubDomain, url.Subdomain)
}
})
}
}


type HttpTransportFunc func(req *http.Request) *http.Response

Expand Down Expand Up @@ -133,5 +165,5 @@ func assertEqual(t *testing.T, expected interface{}, actual interface{}) {
if expected == actual {
return
}
t.Errorf("Received %v (type %v), expected %v (type %v)", expected, reflect.TypeOf(expected), actual, reflect.TypeOf(actual))
t.Errorf("Received %v (type %v), expected %v (type %v)", actual, reflect.TypeOf(actual), expected, reflect.TypeOf(expected))
}

0 comments on commit b946c2d

Please sign in to comment.