Skip to content

Commit

Permalink
Merge abstraction branch
Browse files Browse the repository at this point in the history
Addresses #1

Squashed commit of the following:

commit b13df52ab83e41c611d187de3148d03dd2238ffd
Author: Nick Krichevsky <[email protected]>
Date:   Sun Oct 13 00:04:16 2019 -0400

    Minor linting

commit 473879f6ce280419f3b4afddec3067b7c44b870b
Author: Nick Krichevsky <[email protected]>
Date:   Sun Oct 13 00:01:35 2019 -0400

    Update README

commit 15ec2e0d75b9e022718824060baf5cc708b2285a
Author: Nick Krichevsky <[email protected]>
Date:   Sun Oct 13 00:00:38 2019 -0400

    Add basic config validation

commit dd0b3956acc9c4aebae00fc060ba04132b013323
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 23:56:30 2019 -0400

    Remove dead config code

commit eaa3ceca090fe390fb1bbfeb425f759fe2b9a5aa
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 23:48:55 2019 -0400

    Improve logging

commit eb08404044944bd3ab75931efecd4011dbc02daa
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 23:35:56 2019 -0400

    Re-add ability to write to log file

commit e88514c19afcd741b488f7ce18ce01e6c3f57211
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 23:24:09 2019 -0400

    Move main into cmd package, refactor to use new interface

commit 5bcd98a46a193071aab7236c8b0207af78870bfa
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 23:09:31 2019 -0400

    Add ability to set ttl of records

commit 8f1dadb8b08a5c09fdfb5d3a88f7e9e976edb8ae
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 23:05:08 2019 -0400

    Add IPSetter for DO

commit 923d3f5e29d220d5d2c7004dbf8bce5d2d35096d
Author: Nick Krichevsky <[email protected]>
Date:   Sat Oct 12 21:54:25 2019 -0400

    Add abstraction for setting IP addresses
  • Loading branch information
ollien committed Oct 13, 2019
1 parent 8f9a70a commit e2731cd
Show file tree
Hide file tree
Showing 7 changed files with 338 additions and 293 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Pinamic DNS
Dynamic DNS for your Raspberry Pi (though it doesn't have to be!). Running the binary updates a DNS record on DigitalOcean.
Dynamic DNS for your Raspberry Pi (though it doesn't have to be!). Running the binary updates a DNS record on DigitalOcean.

## Installation
Run the binary (whether in a shell or a cron job) in the same directory as a `config.json`. The `config.json` must contain the following values.
Expand All @@ -21,4 +21,3 @@ Run the binary (whether in a shell or a cron job) in the same directory as a `co
|-------------|---------------------------------------------------------------------|
|--config, -c |Set a path to a `config.json`, if not `./config.json` |
|--logfile, -l|Redirect output to a logfile |
|--silent |Disable all output to stdout. Errors will still be reported to stderr|
67 changes: 67 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package main

import (
"encoding/json"
"errors"
"os"

"golang.org/x/oauth2"
)

const defaultConfigPath = "./config.json"

// Config holds the configuration for the application
// Implements oauth2.TokenSource
type Config struct {
AccessToken string `json:"access_token"`
DNSConfig DNSConfig `json:"dns_config"`
}

// DNSConfig represents the config of the DNS records that will be updated.
type DNSConfig struct {
Domain string `json:"domain"`
Name string `json:"name"`
TTL int `json:"ttl"`
}

// NewConfig reads the file located at filepath and returns a new Config
func NewConfig(filepath string) (Config, error) {
configReader, err := os.Open(filepath)
if err != nil {
return Config{}, err
}

defer configReader.Close()

configDecoder := json.NewDecoder(configReader)
var config Config
err = configDecoder.Decode(&config)
if err != nil {
return Config{}, err
}

return config, config.validate()
}

// validate returns an error if the config is invalid.
func (config Config) validate() error {
if config.AccessToken == "" {
return errors.New("access token must be specified in config")
} else if config.DNSConfig.Domain == "" {
return errors.New("domain must be specified in config")
} else if config.DNSConfig.Name == "" {
return errors.New("name must be specified in config")
} else if config.DNSConfig.TTL == 0 {
return errors.New("ttl must be specified in config")
}

return nil
}

// Token returns a new oauth2.token object.
// Required for config to implement oauth2.TokenSource
func (config Config) Token() (*oauth2.Token, error) {
return &oauth2.Token{
AccessToken: config.AccessToken,
}, nil
}
100 changes: 100 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package main

import (
"io/ioutil"
"log"
"net"
"net/http"
"os"
"strings"

"github.com/ogier/pflag"
pinamicdns "github.com/ollien/pinamic-dns"
"github.com/ollien/xtrace"
)

//DNSStatusCode represents the result of what CreateOrUpdateRecord did.
type DNSStatusCode int

//DNSResult represents the result of running CreateOrUpdateRecord, including information of its run.
type DNSResult struct {
IP string
StatusCode DNSStatusCode
}

//Possible results for DNSResult
const (
StatusIPSet DNSStatusCode = iota
StatusIPUpdated
StatusIPAlreadySet
)

func getIP() (net.IP, error) {
res, err := http.Get("http://checkip.amazonaws.com/")

if err != nil {
return nil, err
}

defer res.Body.Close()
resData, err := ioutil.ReadAll(res.Body)

if err != nil {
return nil, err
}

rawIP := strings.Trim(string(resData), "\n")

return net.ParseIP(rawIP), nil
}

func main() {
configPath := ""
logFilePath := ""
pflag.StringVarP(&configPath, "config", "c", defaultConfigPath, "Set a path to a config.json")
pflag.StringVarP(&logFilePath, "logfile", "l", "", "Redirect output to a log file.")
pflag.Parse()

logWriter := os.Stderr
if logFilePath != "" {
logFile, err := os.OpenFile(logFilePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}

defer logFile.Close()
logWriter = logFile
}
logger := log.New(logWriter, "", log.LstdFlags)

config, err := NewConfig(configPath)
if err != nil {
logger.Fatal(err)
}

var setter pinamicdns.IPSetter
setter, err = pinamicdns.NewDigitalOceanIPSetter(config, pinamicdns.DigitalOceanRecordTTL(config.DNSConfig.TTL))
ip, err := getIP()
if err != nil {
logger.Fatalf("Could not get IP to update with: %s", err)
}

err = setter.SetIP(config.DNSConfig.Domain, config.DNSConfig.Name, ip)
if err != nil {
logger.Printf("Could not update record: %s", err)
tracer, tracerErr := xtrace.NewTracer(err)
if tracerErr != nil {
logger.Fatalf("Could not produce error trace: %s", err)
}

traceErr := tracer.Trace(logWriter)
if traceErr != nil {
logger.Fatalf("Could not produce error trace: %s", err)
}
// HACK: Write a newline so there's one after the trace
// Should probably be done in xtrace
logWriter.Write([]byte("\n"))

os.Exit(1)
}
}
75 changes: 0 additions & 75 deletions config.go

This file was deleted.

Loading

0 comments on commit e2731cd

Please sign in to comment.