This commit is contained in:
Jay 2019-05-09 16:13:25 +08:00
parent e6f22deb49
commit 4fa99f16bd
11 changed files with 306 additions and 9 deletions

9
.drone.yml Normal file
View File

@ -0,0 +1,9 @@
kind: pipeline
name: build_release
steps:
- name: test and build
image: golang
commands:
- go test
- go build

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config.yml

3
go.mod
View File

@ -4,5 +4,8 @@ go 1.12
require ( require (
git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349
github.com/json-iterator/go v1.1.6
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 v2.2.2
) )

7
go.sum
View File

@ -1,5 +1,12 @@
git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 h1:V6ifeiJ3ExnjaUylTOz37n6z5uLwm6fjKjnztbTCaQI= git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 h1:V6ifeiJ3ExnjaUylTOz37n6z5uLwm6fjKjnztbTCaQI=
git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0= git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0=
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

17
main.go
View File

@ -4,6 +4,7 @@ import (
"log" "log"
"git.trj.tw/golang/go-ddns-client/module/config" "git.trj.tw/golang/go-ddns-client/module/config"
"git.trj.tw/golang/go-ddns-client/module/ddns"
"git.trj.tw/golang/go-ddns-client/module/option" "git.trj.tw/golang/go-ddns-client/module/option"
) )
@ -19,4 +20,20 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
data, err := ddns.GetDNSSetting()
if err != nil {
log.Fatal(err)
}
if len(data.V4) > 0 {
if err = ddns.SendRequest(true, data.V4); err != nil {
log.Fatal(err)
}
}
if len(data.V6) > 0 {
if err = ddns.SendRequest(false, data.V6); err != nil {
log.Fatal(err)
}
}
} }

View File

@ -71,4 +71,31 @@ func LoadConfig(p ...string) error {
func GetConfig() *Config { return conf } func GetConfig() *Config { return conf }
// GetV4Data - // GetV4Data -
func (p DomainData) GetV4Data() {} func (p DomainData) GetV4Data() DomainData {
domain := DomainData{}
domain.Name = p.Name
if len(p.Records) == 0 {
return domain
}
for _, it := range p.Records {
if it.Type == "A" {
domain.Records = append(domain.Records, it)
}
}
return domain
}
// GetV6Data -
func (p DomainData) GetV6Data() DomainData {
domain := DomainData{}
domain.Name = p.Name
if len(p.Records) == 0 {
return domain
}
for _, it := range p.Records {
if it.Type == "AAAA" {
domain.Records = append(domain.Records, it)
}
}
return domain
}

View File

@ -0,0 +1,78 @@
package config
import (
"os"
"path"
"reflect"
"testing"
)
func TestLoadConfig(t *testing.T) {
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
p := path.Join(wd, "../..", "config.default.yml")
err = LoadConfig(p)
if err != nil {
t.Fatal(err)
}
}
func TestGetConfig(t *testing.T) {
conf := GetConfig()
if conf == nil {
t.Fail()
}
}
func TestDomainData_GetV6Data(t *testing.T) {
type fields struct {
Name string
Records []RecordData
}
tests := []struct {
name string
fields fields
want DomainData
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := DomainData{
Name: tt.fields.Name,
Records: tt.fields.Records,
}
if got := p.GetV6Data(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("DomainData.GetV6Data() = %v, want %v", got, tt.want)
}
})
}
}
func TestDomainData_GetV4Data(t *testing.T) {
type fields struct {
Name string
Records []RecordData
}
tests := []struct {
name string
fields fields
want DomainData
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := DomainData{
Name: tt.fields.Name,
Records: tt.fields.Records,
}
if got := p.GetV4Data(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("DomainData.GetV4Data() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -2,24 +2,117 @@ package ddns
import ( import (
"errors" "errors"
"io/ioutil"
"log"
"net/http"
"net/textproto"
"net/url"
"bytes"
"git.trj.tw/golang/go-ddns-client/module/config" "git.trj.tw/golang/go-ddns-client/module/config"
jsoniter "github.com/json-iterator/go"
) )
var json = jsoniter.ConfigCompatibleWithStandardLibrary
// Errors // Errors
var ( var (
ErrNoDomain = errors.New("No Domain Setting") ErrNoDomain = errors.New("No Domain Setting")
ErrAPIResp = errors.New("api call not success")
) )
// SendDNSSetting - // DNSSetting -
func SendDNSSetting() error { type DNSSetting struct {
V4 []config.DomainData
V6 []config.DomainData
}
// GetDNSSetting -
func GetDNSSetting() (DNSSetting, error) {
setting := DNSSetting{}
conf := config.GetConfig() conf := config.GetConfig()
if len(conf.Domains) == 0 { if len(conf.Domains) == 0 {
return ErrNoDomain return setting, ErrNoDomain
} }
v4Data := make([]config.DomainData, 0)
v6Data := make([]config.DomainData, 0)
for _, it := range conf.Domains {
v4 := it.GetV4Data()
if len(v4.Records) > 0 {
v4Data = append(v4Data, v4)
}
v6 := it.GetV6Data()
if len(v6.Records) > 0 {
v6Data = append(v6Data, v6)
}
}
setting.V4 = v4Data
setting.V6 = v6Data
return setting, nil
}
// SendRequest -
func SendRequest(v4 bool, data []config.DomainData) error {
conf := config.GetConfig()
var baseURL string
if v4 {
baseURL = conf.URL.V4
} else {
baseURL = conf.URL.V6
}
token := conf.VerifyValue
if len(baseURL) == 0 || len(token) == 0 {
return errors.New("server setting error")
}
body := struct {
Domains []config.DomainData `json:"domains"`
}{}
body.Domains = data
byteData, err := json.Marshal(body)
if err != nil {
return err
}
log.Println("send data :: ", string(byteData))
apiURL, err := url.Parse(baseURL)
if err != nil {
return err
}
apiURL, err = apiURL.Parse("/api/ddns")
if err != nil {
return err
}
reader := bytes.NewReader(byteData)
req, err := http.NewRequest("POST", apiURL.String(), reader)
if err != nil {
return err
}
req.Header.Set(textproto.CanonicalMIMEHeaderKey("X-Mtfos-Key"), token)
req.Header.Set(textproto.CanonicalMIMEHeaderKey("Content-Type"), "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
bodyByte, err := ioutil.ReadAll(resp.Body)
if err == nil {
log.Println("body ::: ", string(bodyByte))
}
if resp.StatusCode != 200 {
return ErrAPIResp
}
return nil return nil
} }
func parseConf(domains []config.DomainData) {
}

28
module/ddns/ddns_test.go Normal file
View File

@ -0,0 +1,28 @@
package ddns
import (
"reflect"
"testing"
)
func TestGetDNSSetting(t *testing.T) {
tests := []struct {
name string
want DNSSetting
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetDNSSetting()
if (err != nil) != tt.wantErr {
t.Errorf("GetDNSSetting() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetDNSSetting() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -17,7 +17,6 @@ func RegOptions() {
flag.StringVar(&opts.Config, "config", "", "config file path - default: `pwd/config.yml`") flag.StringVar(&opts.Config, "config", "", "config file path - default: `pwd/config.yml`")
flag.StringVar(&opts.Config, "f", "", "config file path - default: `pwd/config.yml`") flag.StringVar(&opts.Config, "f", "", "config file path - default: `pwd/config.yml`")
flag.BoolVar(&opts.Help, "help", false, "show help") flag.BoolVar(&opts.Help, "help", false, "show help")
flag.BoolVar(&opts.Once, "once", false, "run once")
flag.Parse() flag.Parse()
} }

View File

@ -0,0 +1,35 @@
package option
import (
"reflect"
"testing"
)
func TestRegOptions(t *testing.T) {
tests := []struct {
name string
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
RegOptions()
})
}
}
func TestGetOptions(t *testing.T) {
tests := []struct {
name string
want *Options
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetOptions(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetOptions() = %v, want %v", got, tt.want)
}
})
}
}