Skip to content

Commit

Permalink
use the new notify library, simplify a lot
Browse files Browse the repository at this point in the history
  • Loading branch information
clinta committed Aug 24, 2017
1 parent df59621 commit a3cb21c
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 109 deletions.
8 changes: 5 additions & 3 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ import:
subpackages:
- inotify
- package: github.com/fsnotify/fsnotify
- package: github.com/rjeczalik/notify
145 changes: 73 additions & 72 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import (
"os/signal"
"path/filepath"
"regexp"
"sync"
"time"

log "github.com/Sirupsen/logrus"

"github.com/fsnotify/fsnotify"
"github.com/rjeczalik/notify"
"github.com/urfave/cli"
)

const (
version = "0.2"
version = "0.3"
)

var resolvContent []byte
var rcl sync.RWMutex

func main() {

app := cli.NewApp()
Expand Down Expand Up @@ -57,23 +61,25 @@ func Run(ctx *cli.Context) error {
log.Info("Debug logging enabled")
}

resolvContent, err := refreshAll([]byte{}, true)
err := refreshAll(true)
if err != nil {
log.WithError(err).Error("Error doing initial refresh")
return err
}

watcher, err := fsnotify.NewWatcher()
resolvEvents := make(chan notify.EventInfo, 8)
err = notify.Watch("/etc/resolv.conf", resolvEvents, notify.Write)
if err != nil {
log.WithError(err).Error("Failed to create new watcher")
log.WithError(err).Error("Failed to resolv.conf notifications")
return err
}

dkrResolvEvents := make(chan notify.EventInfo, 256)
err = notify.Watch("/var/lib/docker/containers/...", dkrResolvEvents, notify.Write)
if err != nil {
log.WithError(err).Error("Failed to container notifications")
return err
}
defer func() {
err := watcher.Close()
if err != nil {
log.WithError(err).Error("Error closing watcher")
}
}()

stop := make(chan struct{})
done := make(chan struct{})
Expand All @@ -91,78 +97,40 @@ func Run(ctx *cli.Context) error {
refresh := ctx.Int("refresh")
go func() {
dockerResolv := regexp.MustCompile("^/var/lib/docker/containers/[A-Za-z0-9]*/resolv.conf$")
dockerDir := regexp.MustCompile("^/var/lib/docker/containers/[A-Za-z0-9]*$")
t := time.NewTicker(time.Duration(max(refresh, 1)) * time.Second)
if refresh <= 0 {
t.Stop()
}
for {
select {
case ev := <-watcher.Events:
if ev.Name == "/etc/resolv.conf" {
resolvContent, err = refreshAll(resolvContent, false)
if err != nil {
log.WithError(err).Error("Error refreshing after /etc/resolv.conf changed")
}
continue
}
if dockerResolv.MatchString(ev.Name) {
go fixResolvConf(ev.Name, resolvContent)
continue
}
if dockerDir.MatchString(ev.Name) {
if ev.Op&fsnotify.Remove != 0 {
watcher.Remove(ev.Name)
continue
}
fi, err := os.Stat(ev.Name)
if err != nil && fi != nil && fi.IsDir() {
err := watcher.Add(ev.Name)
if err != nil {
log.WithError(err).WithField("dir", ev.Name).Error("Error adding watch")
}
go fixResolvConf(ev.Name+"/resolv.conf", resolvContent)
}
continue
}
continue
case <-t.C:
resolvContent, err = refreshAll(resolvContent, true)
err = refreshAll(true)
if err != nil {
log.WithError(err).Error("Error during scheduled refresh")
}
continue
case ev := <-dkrResolvEvents:
if !dockerResolv.MatchString(ev.Path()) {
continue
}
go fixResolvConf(ev.Path())
case <-resolvEvents:
go func() {
err = refreshAll(false)
if err != nil {
log.WithError(err).Error("Error refreshing after /etc/resolv.conf changed")
}
}()
case <-stop:
notify.Stop(dkrResolvEvents)
notify.Stop(resolvEvents)
rcl.Lock() // Ensure all writing is done by locking rcl
close(done)
return
}
}
}()

err = watcher.Add("/var/lib/docker/containers/")
if err != nil {
log.WithError(err).Error("Failed to add container watch")
return err
}
err = watcher.Add("/etc")
if err != nil {
log.WithError(err).Error("Failed to add resolv.conf watch")
return err
}
conts, err := filepath.Glob("/var/lib/docker/containers/*")
if err != nil {
log.WithError(err).Error("Failed to list existing containers")
return err
}
if conts != nil {
for _, c := range conts {
err := watcher.Add(c)
if err != nil {
log.WithError(err).WithField("container", c).Error("Error adding watch for container")
}
}
}

c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
defer close(c)
Expand All @@ -175,30 +143,36 @@ func Run(ctx *cli.Context) error {
return nil
}

func refreshAll(resolvContent []byte, force bool) (newResolvContent []byte, err error) {
newResolvContent, err = ioutil.ReadFile("/etc/resolv.conf")
func refreshAll(force bool) error {
newResolvContent, err := ioutil.ReadFile("/etc/resolv.conf")
if err != nil {
log.WithError(err).Error("Failed to read /etc/resolv.conf")
return
return err
}
rcl.RLock()
if bytes.Equal(newResolvContent, resolvContent) {
log.Debug("/etc/resolv.conf unchanged")
if !force {
return
rcl.RUnlock()
return nil
}
}
rcl.RUnlock()
rcl.Lock()
resolvContent = newResolvContent
log.WithField("content", string(resolvContent)).Debug("/etc/resov.conf content retrieved")
rcl.Unlock()
resolvs, err := filepath.Glob("/var/lib/docker/containers/*/resolv.conf")
if err != nil {
log.WithError(err).Error("Failed to list existing resolv.conf files")
return
return err
}
if resolvs != nil {
for _, r := range resolvs {
go fixResolvConf(r, newResolvContent)
go fixResolvConf(r)
}
}
return
return nil
}

func max(a, b int) int {
Expand All @@ -207,3 +181,30 @@ func max(a, b int) int {
}
return b
}

func fixResolvConf(path string) {
_, err := os.Stat(path)
if err != nil {
log.WithField("Path", path).Debug("File does not exist")
return
}

c, err := ioutil.ReadFile(path)
if err != nil {
log.WithError(err).WithField("Path", path).Error("Failed to read file")
return
}

rcl.RLock()
defer rcl.RUnlock()
if bytes.Equal(c, resolvContent) {
log.WithField("Path", path).Debug("File already has correct content")
return
}

err = ioutil.WriteFile(path, resolvContent, 0644)
if err != nil {
log.WithError(err).WithField("Path", path).Error("Failed to write to file")
}
log.WithField("Path", path).Debug("File content updated")
}
34 changes: 0 additions & 34 deletions util.go

This file was deleted.

0 comments on commit a3cb21c

Please sign in to comment.