135 lines
3.3 KiB
Go
135 lines
3.3 KiB
Go
package ddnsclient
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"os/signal"
|
|
"reflect"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/datahearth/ddnsclient/pkg/providers"
|
|
"github.com/datahearth/ddnsclient/pkg/providers/google"
|
|
"github.com/datahearth/ddnsclient/pkg/providers/ovh"
|
|
"github.com/datahearth/ddnsclient/pkg/watcher"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var (
|
|
ErrSbsLen = errors.New("subdomains len is 0")
|
|
ErrInvalidProvider = errors.New("invalid provider name")
|
|
ErrWatchersConfigLen = errors.New("watcher configuration needs at least one [watcherd] and [providerd] configuration")
|
|
ErrWatcherCreationLen = errors.New("no valid watchers were created. Checkout [watchers] configuration and its [providers] configuration")
|
|
)
|
|
|
|
// Start create a new instance of ddns-client
|
|
func Start(logger logrus.FieldLogger, config ClientConfig) error {
|
|
log := logger.WithFields(logrus.Fields{
|
|
"pkg": "ddnsclient",
|
|
"component": "root",
|
|
})
|
|
|
|
fields := reflect.ValueOf(config.Watchers)
|
|
ws := []watcher.Watcher{}
|
|
|
|
// * check providers and watchers config
|
|
// todo: invalid condition but while still exit in the next step. To be corrected
|
|
if fields.NumField() == 0 || reflect.ValueOf(config.Providers).NumField() == 0 {
|
|
return ErrWatchersConfigLen
|
|
}
|
|
|
|
for i := 0; i < fields.NumField(); i++ {
|
|
providerName := strings.ToLower(fields.Type().Field(i).Name)
|
|
|
|
w, err := CreateWatcher(providerName, config.WebIP, logger, config.Watchers, config.Providers, config.PendingDnsPropagation)
|
|
if err != nil {
|
|
logger.Warnf("Provider error: %v. Skipping...\n", err.Error())
|
|
continue
|
|
}
|
|
|
|
ws = append(ws, w)
|
|
}
|
|
|
|
// * check for valid created watchers
|
|
if len(ws) == 0 {
|
|
return ErrWatcherCreationLen
|
|
}
|
|
|
|
// * create signal watcher
|
|
sigc := make(chan os.Signal, 1)
|
|
signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
|
defer close(sigc)
|
|
|
|
// * create close and error channel
|
|
chClose := make(chan struct{})
|
|
chErr := make(chan error)
|
|
defer close(chClose)
|
|
defer close(chErr)
|
|
|
|
logger.Infoln("Start watching periodically for changes!")
|
|
// * run every created watchers in goroutines
|
|
for _, w := range ws {
|
|
tickTime := config.UpdateTime
|
|
if tickTime == 0 {
|
|
tickTime = 180
|
|
}
|
|
|
|
t := time.NewTicker(time.Duration(tickTime) * time.Second)
|
|
go w.Run(t, chClose, chErr)
|
|
}
|
|
|
|
// * listening for errors and exit signal
|
|
for {
|
|
select {
|
|
case err := <-chErr:
|
|
log.Errorln(err.Error())
|
|
continue
|
|
case <-sigc:
|
|
log.Infoln("Interrupt signal received. Stopping watcher...")
|
|
chClose <- struct{}{}
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func CreateWatcher(provider, webIP string, logger logrus.FieldLogger, wc WatcherConfig, ps Providers, pendingDnsPropagation int) (watcher.Watcher, error) {
|
|
var sbs []string
|
|
var p providers.Provider
|
|
var err error
|
|
|
|
// * check for implemented providers
|
|
switch provider {
|
|
case "ovh":
|
|
logger.Debugln("create OVH provider")
|
|
p, err = ovh.NewOVH(logger, &ps.Ovh)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sbs = wc.Ovh
|
|
|
|
case "google":
|
|
logger.Debugln("create GOOGLE provider")
|
|
p, err = google.NewGoogle(logger, &ps.Google)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sbs = wc.Google
|
|
|
|
default:
|
|
return nil, ErrInvalidProvider
|
|
}
|
|
|
|
if len(sbs) == 0 {
|
|
return nil, ErrSbsLen
|
|
}
|
|
|
|
// * create provider's watcher
|
|
w, err := watcher.NewWatcher(logger, p, sbs, webIP, provider, pendingDnsPropagation)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return w, nil
|
|
}
|