Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
honwen committed Dec 16, 2016
1 parent 22106c5 commit c5e0c33
Show file tree
Hide file tree
Showing 5 changed files with 357 additions and 1 deletion.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# Folders
_obj
_test
.vscode/
release/

# Architecture specific extensions/prefixes
*.[568vq]
Expand All @@ -22,3 +24,8 @@ _testmain.go
*.exe
*.test
*.prof
*.upx

debug
aliyun-ddns-cli
aliddns*
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# aliyun-ddns-cli
aliyun-ddns-cli golang
```
NAME:
aliddns - aliyun-ddns-cli
USAGE:
aliyun-ddns-cli [global options] command [command options] [arguments...]
VERSION:
XXXXXX
COMMANDS:
help, h Shows a list of commands or help for one command
DDNS:
list List AliYun's DNS DomainRecords Record
update Update AliYun's DNS DomainRecords Record
auto-update Auto-Update AliYun's DNS DomainRecords Record, Get IP using http://ip.cn
GET-IP:
getip Get IP using http://ip.cn
getip-intl Get IP using http://ipinfo.io
GLOBAL OPTIONS:
--access-key-id value, --id value AliYun's Access Key ID
--access-key-secret value, --secret value AliYun's Access Key Secret
--help, -h show help
--version, -v print the version
EXAMPLE:
aliddns --id ${AccessKeyID} --secret ${AccessKeySecret} auto-update --domain ddns.example.win
aliddns --id ${AccessKeyID} --secret ${AccessKeySecret} update --domain ddns.example.win --ipaddr $(ifconfig pppoe-wan | sed -n '2{s/[^0-9]*://;s/[^0-9.].*//p}')
```
52 changes: 52 additions & 0 deletions build-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash
MD5='md5sum'
unamestr=`uname`
if [[ "$unamestr" == 'Darwin' ]]; then
MD5='md5'
fi

UPX=false
if hash upx 2>/dev/null; then
UPX=true
fi

VERSION=`date -u +%Y%m%d`
LDFLAGS="-X main.version=$VERSION -s -w -linkmode external -extldflags -static"
GCFLAGS=""

OSES=(windows linux darwin freebsd)
ARCHS=(amd64 386)
rm -rf ./release
mkdir -p ./release
for os in ${OSES[@]}; do
for arch in ${ARCHS[@]}; do
suffix=""
if [ "$os" == "windows" ]; then
suffix=".exe"
LDFLAGS="-X main.version=$VERSION -s -w"
fi
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./release/aliddns_${os}_${arch}${suffix} github.com/chenhw2/aliyun-ddns-cli
if $UPX; then upx -9 ./release/aliddns_${os}_${arch}${suffix};fi
tar -zcf ./release/aliddns_${os}-${arch}-$VERSION.tar.gz ./release/aliddns_${os}_${arch}${suffix}
$MD5 ./release/aliddns_${os}-${arch}-$VERSION.tar.gz
done
done

# ARM
ARMS=(5 6 7)
for v in ${ARMS[@]}; do
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./release/aliddns_arm$v github.com/chenhw2/aliyun-ddns-cli
done
if $UPX; then upx -9 ./release/aliddns_arm*;fi
tar -zcf ./release/aliddns_arm-$VERSION.tar.gz ./release/aliddns_arm*
$MD5 ./release/aliddns_arm-$VERSION.tar.gz

#MIPS32LE
LDFLAGS="-X main.version=$VERSION -s -w"
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./release/aliddns_mipsle github.com/chenhw2/aliyun-ddns-cli
env CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./release/aliddns_mips github.com/chenhw2/aliyun-ddns-cli

if $UPX; then upx -9 ./release/aliddns_mips**;fi
tar -zcf ./release/aliddns_mipsle-$VERSION.tar.gz ./release/aliddns_mipsle
tar -zcf ./release/aliddns_mips-$VERSION.tar.gz ./release/aliddns_mips
$MD5 ./release/aliddns_mipsle-$VERSION.tar.gz
235 changes: 235 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package main

import (
"errors"
"fmt"
"os"

"regexp"

"github.com/denverdino/aliyungo/dns"
"github.com/urfave/cli"
)

// AccessKey from https://ak-console.aliyun.com/#/accesskey
type AccessKey struct {
ID string
Secret string
}

func (ak *AccessKey) isFiled() bool {
return len(ak.ID) > 0 && len(ak.Secret) > 0
}

func (ak AccessKey) String() string {
return fmt.Sprintf("Access Key: [ ID: %s ;\t Secret: %s ]", ak.ID, ak.Secret)
}

func (ak *AccessKey) list(domain string) (dnsRecords []dns.RecordType, err error) {
client := dns.NewClient(ak.ID, ak.Secret)
res, err := client.DescribeDomainRecords(
&dns.DescribeDomainRecordsArgs{
DomainName: domain,
})
if err != nil {
return
}
dnsRecords = res.DomainRecords.Record
return
}

func (ak *AccessKey) update(recordID, rr, value string) (err error) {
client := dns.NewClient(ak.ID, ak.Secret)
_, err = client.UpdateDomainRecord(
&dns.UpdateDomainRecordArgs{
RecordId: recordID,
RR: rr,
Value: value,
Type: dns.ARecord,
})
return
}

var (
accessKey AccessKey
version = "MISSING build version [git hash]"
)

func main() {
app := cli.NewApp()
app.Name = "aliddns"
app.Usage = "aliyun-ddns-cli"
app.Version = version
app.Commands = []cli.Command{
{
Name: "list",
Category: "DDNS",
Usage: "List AliYun's DNS DomainRecords Record",
Flags: []cli.Flag{
cli.StringFlag{
Name: "domain, d",
Usage: "specify `DomainName`. like aliyun.com",
},
},
Action: func(c *cli.Context) error {
if err := appInit(c); err != nil {
return err
}
// fmt.Println(c.Command.Name, "task: ", accessKey, c.String("domain"))
dnsRecords, err := accessKey.list(c.String("domain"))
if err != nil {
fmt.Printf("%+v", err)
} else {
for _, v := range dnsRecords {
fmt.Println(v.RR+`.`+v.DomainName, v.Value)
}
}
return nil
},
},
{
Name: "update",
Category: "DDNS",
Usage: "Update AliYun's DNS DomainRecords Record",
Flags: []cli.Flag{
cli.StringFlag{
Name: "domain, d",
Usage: "specify `DomainName`. like ddns.aliyun.com",
},
cli.StringFlag{
Name: "ipaddr, i",
Usage: "specify `IP`. like 1.2.3.4",
},
},
Action: func(c *cli.Context) error {
if err := appInit(c); err != nil {
return err
}
// fmt.Println(c.Command.Name, "task: ", accessKey, c.String("domain"), c.String("ipaddr"))
rr := regexp.MustCompile(`\.[^\.]*`).ReplaceAllString(c.String("domain"), "")
domain := regexp.MustCompile(`^[^\.]*\.`).ReplaceAllString(c.String("domain"), "")
// fmt.Println(rr, domain)
dnsRecords, err := accessKey.list(domain)
var target *dns.RecordType
if err != nil {
fmt.Printf("%+v", err)
} else {
for i := range dnsRecords {
if dnsRecords[i].RR == rr {
target = &dnsRecords[i]
break
}
}
}
if target != nil {
ipaddr := getIPipcn()
if ipaddr == target.Value {
fmt.Println(target.RR+`.`+target.DomainName, ipaddr)
return nil
}
err = accessKey.update(target.RecordId, target.RR, c.String("ipaddr"))
if err != nil {
fmt.Printf("%+v", err)
} else {
fmt.Println(target.RR+`.`+target.DomainName, c.String("ipaddr"))
}
} else {
fmt.Println("Can't Find target")
}
return nil
},
},
{
Name: "auto-update",
Category: "DDNS",
Usage: "Auto-Update AliYun's DNS DomainRecords Record, Get IP using http://ip.cn",
Flags: []cli.Flag{
cli.StringFlag{
Name: "domain, d",
Usage: "specify `DomainName`. like ddns.aliyun.com",
},
},
Action: func(c *cli.Context) error {
if err := appInit(c); err != nil {
return err
}
// fmt.Println(c.Command.Name, "task: ", accessKey, c.String("domain"))
rr := regexp.MustCompile(`\.[^\.]*`).ReplaceAllString(c.String("domain"), "")
domain := regexp.MustCompile(`^[^\.]*\.`).ReplaceAllString(c.String("domain"), "")
// fmt.Println(rr, domain)
dnsRecords, err := accessKey.list(domain)
var target *dns.RecordType
if err != nil {
fmt.Printf("%+v", err)
} else {
for i := range dnsRecords {
if dnsRecords[i].RR == rr {
target = &dnsRecords[i]
break
}
}
}
if target != nil {
ipaddr := getIPipcn()
if ipaddr == target.Value {
fmt.Println(target.RR+`.`+target.DomainName, ipaddr)
return nil
}
err = accessKey.update(target.RecordId, target.RR, ipaddr)
if err != nil {
fmt.Printf("%+v", err)
} else {
fmt.Println(target.RR+`.`+target.DomainName, ipaddr)
}
} else {
fmt.Println("Can't Find target")
}
return nil
},
},
{
Name: "getip",
Category: "GET-IP",
Usage: "Get IP using http://ip.cn",
Action: func(c *cli.Context) error {
// fmt.Println(c.Command.Name, "task: ", c.Command.Usage)
fmt.Println(getIPipcn())
return nil
},
},
{
Name: "getip-intl",
Category: "GET-IP",
Usage: "Get IP using http://ipinfo.io",
Action: func(c *cli.Context) error {
// fmt.Println(c.Command.Name, "task: ", c.Command.Usage)
fmt.Println(getIPipio())
return nil
},
},
}
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "access-key-id, id",
Usage: "AliYun's Access Key ID",
},
cli.StringFlag{
Name: "access-key-secret, secret",
Usage: "AliYun's Access Key Secret",
},
}
app.Action = func(c *cli.Context) error {
return appInit(c)
}
app.Run(os.Args)
}

func appInit(c *cli.Context) error {
accessKey.ID = c.GlobalString("access-key-id")
accessKey.Secret = c.GlobalString("access-key-secret")
if !accessKey.isFiled() {
cli.ShowAppHelp(c)
return errors.New("access-key is empty")
}
return nil
}
29 changes: 29 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"io/ioutil"
"net/http"
"regexp"
)

const regxIP = `(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)`

func getIPipcn() (ip string) {
res, err := http.Get("http://ip.cn")
if err == nil {
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
ip = regexp.MustCompile(regxIP).FindString(string(body))
}
return
}

func getIPipio() (ip string) {
res, err := http.Get("http://ipinfo.io")
if err == nil {
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
ip = regexp.MustCompile(regxIP).FindString(string(body))
}
return
}

0 comments on commit c5e0c33

Please sign in to comment.