diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c293179 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +# Testing Configurations +config.json \ No newline at end of file diff --git a/api/api.go b/api/api.go new file mode 100644 index 0000000..ec97d6f --- /dev/null +++ b/api/api.go @@ -0,0 +1,90 @@ +package api + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" +) + +const ( + productionUrl = "https://api.name.com/" + devUrl = "https://api.dev.name.com/" +) + +type API struct { + baseUrl string + username string + token string +} + +type DNSRecord struct { + RecordId string `json:"record_id"` + Name string `json:"name"` + Type string `json:"type"` + Content string `json:"content"` + Ttl string `json:"ttl"` + CreateDate string `json:"create_date"` +} + +type resultResponse struct { + Code int `json:"code"` + Message string `json:"message"` +} + +func NewAPI(c Config) API { + a := API{username: c.Username, token: c.Token} + + if c.Debug { + a.baseUrl = devUrl + } else { + a.baseUrl = productionUrl + } + + return a +} + +func (api API) performRequest(method, url string, body io.Reader) (response []byte, err error) { + var client http.Client + req, err := http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + + req.Header.Add("api-username", api.username) + req.Header.Add("api-token", api.token) + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + return ioutil.ReadAll(resp.Body) +} + +func (api API) GetRecords(hostname string) (records []DNSRecord, err error) { + resp, err := api.performRequest("GET", fmt.Sprintf("%s%s%s", api.baseUrl, "api/dns/list/", hostname), nil) + if err != nil { + return nil, err + } + + var result struct { + Result resultResponse + Records []DNSRecord + } + + err = json.Unmarshal(resp, &result) + if err != nil { + return nil, err + } + + // Make sure the API call was successful + if result.Result.Code != 100 { + return nil, errors.New(result.Result.Message) + } + + return result.Records, nil +} diff --git a/api/config.go b/api/config.go new file mode 100644 index 0000000..b4ae90b --- /dev/null +++ b/api/config.go @@ -0,0 +1,32 @@ +package api + +import ( + "encoding/json" + "io/ioutil" +) + +type Config struct { + Debug bool `json:"debug"` + Domains []string `json:"domains"` + Interval int `json:"interval"` + Token string `json:"token"` + Username string `json:"username"` +} + +func LoadConfigs(path string) ([]Config, error) { + var configs struct { + Configs []Config + } + + file, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + err = json.Unmarshal(file, &configs) + if err != nil { + return nil, err + } + + return configs.Configs, nil +} diff --git a/api/config_test.go b/api/config_test.go new file mode 100644 index 0000000..3fce800 --- /dev/null +++ b/api/config_test.go @@ -0,0 +1,38 @@ +package api + +import ( + "reflect" + "testing" +) + +var expectedConfigs []Config + +func init() { + expectedConfigs = []Config{ + Config{ + Username: "debug-account", + Token: "asdasdasdasdasdad", + Interval: 60, + Debug: true, + Domains: []string{"test.com", "fake.com"}, + }, + Config{ + Username: "production-account", + Token: "123123123123", + Interval: 3600, + Domains: []string{"live.com", "abc.live.com"}, + }, + } +} + +func TestLoadConfigs(t *testing.T) { + configs, err := LoadConfigs("./config_test.json") + + if err != nil { + t.Fatalf("Failed to load configs: %s\n", err) + } + + if !reflect.DeepEqual(expectedConfigs, configs) { + t.Fatalf("Unexpected configuration") + } +} diff --git a/api/config_test.json b/api/config_test.json new file mode 100644 index 0000000..fbad18f --- /dev/null +++ b/api/config_test.json @@ -0,0 +1,17 @@ +{ + "configs": [ + { + "username": "debug-account", + "token": "asdasdasdasdasdad", + "interval": 60, + "debug": true, + "domains": [ "test.com", "fake.com" ] + }, + { + "username": "production-account", + "token": "123123123123", + "interval": 3600, + "domains": [ "live.com", "abc.live.com" ] + } + ] +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..672e221 --- /dev/null +++ b/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "github.com/mfycheng/name-dyndns/api" + "os" +) + +const ( + defaultConfigPath = "./config.json" +) + +func main() { + configs, err := api.LoadConfigs(defaultConfigPath) + if err != nil { + fmt.Println("Error loading config:", err) + os.Exit(1) + return + } + + fmt.Printf("Successfully loaded %d configs\n", len(configs)) + for _, config := range configs { + fmt.Println("Processing config", config) + } +}