| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -3,6 +3,7 @@ package main
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					"fmt"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					"os"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					"strings"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					"sync"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					"git.xbudex.com/buddy/update-dns/dns"
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -12,6 +13,27 @@ import (
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					"github.com/urfave/cli"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				var validTypes = []string{"A", "AAAA", "TXT"}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				type typeFlag struct {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					value string
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				func (f *typeFlag) Set(v string) error {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					value := strings.ToUpper(v)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for _, val := range validTypes {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if val == value {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							f.value = val
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							return nil
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return errors.Errorf("invalid type %s, expected %v", v, validTypes)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				func (f *typeFlag) String() string {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return f.value
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				func main() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					app := cli.NewApp()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					app.Name = "update-dns"
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -20,10 +42,28 @@ func main() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					app.Action = action
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					app.Flags = []cli.Flag{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cli.GenericFlag{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Name:  "type",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Value: &typeFlag{value: "AAAA"},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Usage: "type of dns record to create",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cli.StringFlag{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Name:  "url",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Name:  "content",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Value: "",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Usage: "content to set manually, defaults to fetching ip address if not set",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cli.StringFlag{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Name:  "get-ipv6-url",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Value: "https://whatismyipv6.buddy.wtf/json",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Usage: "url to use to get public ip address",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Usage: "url to use to get public IPv6 address",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cli.StringFlag{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Name:  "get-ipv4-url",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Value: "https://whatismyipv4.buddy.wtf/json",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							Usage: "url to use to get public IPv4 address",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cli.StringFlag{
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -49,21 +89,42 @@ func action(context *cli.Context) error {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					host := context.Args().Get(0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					kind := context.Generic("type").(*typeFlag).value
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wg.Add(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ipClient := &ip.Client{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						URLv4: "https://whatismyipv4.buddy.wtf/json",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						URLv6: "https://whatismyipv6.buddy.wtf/json",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						URLv4: context.String("get-ipv4-url"),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						URLv6: context.String("get-ipv6-url"),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					var getIPError error
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					var ip string
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					var content string
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					go func() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						defer wg.Done()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if result, err := ipClient.GetIPv6(); err != nil {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						var err error
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						result := context.String("content")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						switch kind {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case "A":
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if result == "" {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								result, err = ipClient.GetIPv4()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case "AAAA":
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if result == "" {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								result, err = ipClient.GetIPv6()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						default:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if result == "" {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								err = errors.Errorf("could not get content for type %s", kind)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								return
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if err != nil {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							getIPError = errors.Wrap(err, "could not get IP address")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ip = result
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							content = result
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -74,8 +135,7 @@ func action(context *cli.Context) error {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wg.Add(1)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					go func() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						defer wg.Done()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						fmt.Println("Getting records")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if results, err := client.GetRecords(host, "AAAA"); err != nil {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if results, err := client.GetRecords(host, kind); err != nil {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							getRecordsError = errors.Wrap(err, "could not get records for host")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							records = results
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -92,16 +152,16 @@ func action(context *cli.Context) error {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return errors.Wrap(getRecordsError, "could no get record")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if len(records) == 1 && records[0].Content == ip {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						fmt.Printf("%s record for %s already set as %s\n", "AAAA", host, ip)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if len(records) == 1 && records[0].Content == content {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						fmt.Printf("%s record for %s already set as %s\n", kind, host, content)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return nil
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if err := client.CreateRecord(host, dns.Record{Type: "AAAA", Content: ip}); err != nil {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if err := client.CreateRecord(host, dns.Record{Type: kind, Content: content}); err != nil {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return errors.Wrap(err, "could not create record")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					fmt.Printf("%s record created for %s as %s\n", "AAAA", host, ip)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					fmt.Printf("%s record created for %s as %s\n", kind, host, content)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					var deleteWG sync.WaitGroup
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for _, record := range records {
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |