Skip to content

Commit a3cb21c

Browse files
committed
use the new notify library, simplify a lot
1 parent df59621 commit a3cb21c

File tree

4 files changed

+79
-109
lines changed

4 files changed

+79
-109
lines changed

glide.lock

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

glide.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ import:
66
subpackages:
77
- inotify
88
- package: github.com/fsnotify/fsnotify
9+
- package: github.com/rjeczalik/notify

main.go

Lines changed: 73 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@ import (
77
"os/signal"
88
"path/filepath"
99
"regexp"
10+
"sync"
1011
"time"
1112

1213
log "github.com/Sirupsen/logrus"
1314

14-
"github.com/fsnotify/fsnotify"
15+
"github.com/rjeczalik/notify"
1516
"github.com/urfave/cli"
1617
)
1718

1819
const (
19-
version = "0.2"
20+
version = "0.3"
2021
)
2122

23+
var resolvContent []byte
24+
var rcl sync.RWMutex
25+
2226
func main() {
2327

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

60-
resolvContent, err := refreshAll([]byte{}, true)
64+
err := refreshAll(true)
6165
if err != nil {
6266
log.WithError(err).Error("Error doing initial refresh")
6367
return err
6468
}
6569

66-
watcher, err := fsnotify.NewWatcher()
70+
resolvEvents := make(chan notify.EventInfo, 8)
71+
err = notify.Watch("/etc/resolv.conf", resolvEvents, notify.Write)
6772
if err != nil {
68-
log.WithError(err).Error("Failed to create new watcher")
73+
log.WithError(err).Error("Failed to resolv.conf notifications")
74+
return err
75+
}
76+
77+
dkrResolvEvents := make(chan notify.EventInfo, 256)
78+
err = notify.Watch("/var/lib/docker/containers/...", dkrResolvEvents, notify.Write)
79+
if err != nil {
80+
log.WithError(err).Error("Failed to container notifications")
6981
return err
7082
}
71-
defer func() {
72-
err := watcher.Close()
73-
if err != nil {
74-
log.WithError(err).Error("Error closing watcher")
75-
}
76-
}()
7783

7884
stop := make(chan struct{})
7985
done := make(chan struct{})
@@ -91,78 +97,40 @@ func Run(ctx *cli.Context) error {
9197
refresh := ctx.Int("refresh")
9298
go func() {
9399
dockerResolv := regexp.MustCompile("^/var/lib/docker/containers/[A-Za-z0-9]*/resolv.conf$")
94-
dockerDir := regexp.MustCompile("^/var/lib/docker/containers/[A-Za-z0-9]*$")
95100
t := time.NewTicker(time.Duration(max(refresh, 1)) * time.Second)
96101
if refresh <= 0 {
97102
t.Stop()
98103
}
99104
for {
100105
select {
101-
case ev := <-watcher.Events:
102-
if ev.Name == "/etc/resolv.conf" {
103-
resolvContent, err = refreshAll(resolvContent, false)
104-
if err != nil {
105-
log.WithError(err).Error("Error refreshing after /etc/resolv.conf changed")
106-
}
107-
continue
108-
}
109-
if dockerResolv.MatchString(ev.Name) {
110-
go fixResolvConf(ev.Name, resolvContent)
111-
continue
112-
}
113-
if dockerDir.MatchString(ev.Name) {
114-
if ev.Op&fsnotify.Remove != 0 {
115-
watcher.Remove(ev.Name)
116-
continue
117-
}
118-
fi, err := os.Stat(ev.Name)
119-
if err != nil && fi != nil && fi.IsDir() {
120-
err := watcher.Add(ev.Name)
121-
if err != nil {
122-
log.WithError(err).WithField("dir", ev.Name).Error("Error adding watch")
123-
}
124-
go fixResolvConf(ev.Name+"/resolv.conf", resolvContent)
125-
}
126-
continue
127-
}
128-
continue
129106
case <-t.C:
130-
resolvContent, err = refreshAll(resolvContent, true)
107+
err = refreshAll(true)
131108
if err != nil {
132109
log.WithError(err).Error("Error during scheduled refresh")
133110
}
134111
continue
112+
case ev := <-dkrResolvEvents:
113+
if !dockerResolv.MatchString(ev.Path()) {
114+
continue
115+
}
116+
go fixResolvConf(ev.Path())
117+
case <-resolvEvents:
118+
go func() {
119+
err = refreshAll(false)
120+
if err != nil {
121+
log.WithError(err).Error("Error refreshing after /etc/resolv.conf changed")
122+
}
123+
}()
135124
case <-stop:
125+
notify.Stop(dkrResolvEvents)
126+
notify.Stop(resolvEvents)
127+
rcl.Lock() // Ensure all writing is done by locking rcl
136128
close(done)
137129
return
138130
}
139131
}
140132
}()
141133

142-
err = watcher.Add("/var/lib/docker/containers/")
143-
if err != nil {
144-
log.WithError(err).Error("Failed to add container watch")
145-
return err
146-
}
147-
err = watcher.Add("/etc")
148-
if err != nil {
149-
log.WithError(err).Error("Failed to add resolv.conf watch")
150-
return err
151-
}
152-
conts, err := filepath.Glob("/var/lib/docker/containers/*")
153-
if err != nil {
154-
log.WithError(err).Error("Failed to list existing containers")
155-
return err
156-
}
157-
if conts != nil {
158-
for _, c := range conts {
159-
err := watcher.Add(c)
160-
if err != nil {
161-
log.WithError(err).WithField("container", c).Error("Error adding watch for container")
162-
}
163-
}
164-
}
165-
166134
c := make(chan os.Signal, 1)
167135
signal.Notify(c, os.Interrupt)
168136
defer close(c)
@@ -175,30 +143,36 @@ func Run(ctx *cli.Context) error {
175143
return nil
176144
}
177145

178-
func refreshAll(resolvContent []byte, force bool) (newResolvContent []byte, err error) {
179-
newResolvContent, err = ioutil.ReadFile("/etc/resolv.conf")
146+
func refreshAll(force bool) error {
147+
newResolvContent, err := ioutil.ReadFile("/etc/resolv.conf")
180148
if err != nil {
181149
log.WithError(err).Error("Failed to read /etc/resolv.conf")
182-
return
150+
return err
183151
}
152+
rcl.RLock()
184153
if bytes.Equal(newResolvContent, resolvContent) {
185154
log.Debug("/etc/resolv.conf unchanged")
186155
if !force {
187-
return
156+
rcl.RUnlock()
157+
return nil
188158
}
189159
}
160+
rcl.RUnlock()
161+
rcl.Lock()
162+
resolvContent = newResolvContent
190163
log.WithField("content", string(resolvContent)).Debug("/etc/resov.conf content retrieved")
164+
rcl.Unlock()
191165
resolvs, err := filepath.Glob("/var/lib/docker/containers/*/resolv.conf")
192166
if err != nil {
193167
log.WithError(err).Error("Failed to list existing resolv.conf files")
194-
return
168+
return err
195169
}
196170
if resolvs != nil {
197171
for _, r := range resolvs {
198-
go fixResolvConf(r, newResolvContent)
172+
go fixResolvConf(r)
199173
}
200174
}
201-
return
175+
return nil
202176
}
203177

204178
func max(a, b int) int {
@@ -207,3 +181,30 @@ func max(a, b int) int {
207181
}
208182
return b
209183
}
184+
185+
func fixResolvConf(path string) {
186+
_, err := os.Stat(path)
187+
if err != nil {
188+
log.WithField("Path", path).Debug("File does not exist")
189+
return
190+
}
191+
192+
c, err := ioutil.ReadFile(path)
193+
if err != nil {
194+
log.WithError(err).WithField("Path", path).Error("Failed to read file")
195+
return
196+
}
197+
198+
rcl.RLock()
199+
defer rcl.RUnlock()
200+
if bytes.Equal(c, resolvContent) {
201+
log.WithField("Path", path).Debug("File already has correct content")
202+
return
203+
}
204+
205+
err = ioutil.WriteFile(path, resolvContent, 0644)
206+
if err != nil {
207+
log.WithError(err).WithField("Path", path).Error("Failed to write to file")
208+
}
209+
log.WithField("Path", path).Debug("File content updated")
210+
}

util.go

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)