mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-20 00:03:53 +01:00
87 lines
1.7 KiB
Go
87 lines
1.7 KiB
Go
package watcher
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/filters"
|
|
D "github.com/yusing/go-proxy/docker"
|
|
E "github.com/yusing/go-proxy/error"
|
|
)
|
|
|
|
type DockerWatcher struct {
|
|
host string
|
|
}
|
|
|
|
func NewDockerWatcher(host string) *DockerWatcher {
|
|
return &DockerWatcher{host: host}
|
|
}
|
|
|
|
func (w *DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.NestedError) {
|
|
eventCh := make(chan Event)
|
|
errCh := make(chan E.NestedError)
|
|
started := make(chan struct{})
|
|
|
|
go func() {
|
|
defer close(errCh)
|
|
|
|
var cl D.Client
|
|
var err E.NestedError
|
|
for range 3 {
|
|
cl, err = D.ConnectClient(w.host)
|
|
if err.IsNotNil() {
|
|
break
|
|
}
|
|
errCh <- E.From(err)
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
if err.IsNotNil() {
|
|
errCh <- E.Failure("connect to docker")
|
|
return
|
|
}
|
|
|
|
cEventCh, cErrCh := cl.Events(ctx, dwOptions)
|
|
started <- struct{}{}
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
errCh <- E.From(<-cErrCh)
|
|
return
|
|
case msg := <-cEventCh:
|
|
containerName, ok := msg.Actor.Attributes["name"]
|
|
if !ok {
|
|
// NOTE: should not happen
|
|
// but if it happens, just ignore it
|
|
continue
|
|
}
|
|
eventCh <- Event{
|
|
ActorName: containerName,
|
|
Action: ActionModified,
|
|
}
|
|
case err := <-cErrCh:
|
|
errCh <- E.From(err)
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
if D.IsErrConnectionFailed(err) {
|
|
time.Sleep(100 * time.Millisecond)
|
|
cEventCh, cErrCh = cl.Events(ctx, dwOptions)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
<-started
|
|
|
|
return eventCh, errCh
|
|
}
|
|
|
|
var dwOptions = types.EventsOptions{Filters: filters.NewArgs(
|
|
filters.Arg("type", "container"),
|
|
filters.Arg("event", "start"),
|
|
filters.Arg("event", "die"), // 'stop' already triggering 'die'
|
|
)}
|