From 35f95926cc0201a2a80424eb4fc6643ebb2d780c Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Sun, 20 Apr 2014 10:56:59 -0700 Subject: [PATCH 1/2] Create utils file for common funcs --- dockerclient.go | 17 ----------------- utils.go | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 utils.go diff --git a/dockerclient.go b/dockerclient.go index c0ed214e15e21..2ed27c9e961a8 100644 --- a/dockerclient.go +++ b/dockerclient.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "net" "net/http" "net/url" "sync/atomic" @@ -27,22 +26,6 @@ func NewDockerClient(daemonUrl string) (*DockerClient, error) { return &DockerClient{u, httpClient, 0}, nil } -func newHTTPClient(u *url.URL) *http.Client { - httpTransport := &http.Transport{} - if u.Scheme == "unix" { - socketPath := u.Path - unixDial := func(proto string, addr string) (net.Conn, error) { - return net.Dial("unix", socketPath) - } - httpTransport.Dial = unixDial - // Override the main URL object so the HTTP lib won't complain - u.Scheme = "http" - u.Host = "unix.sock" - } - u.Path = "" - return &http.Client{Transport: httpTransport} -} - func (client *DockerClient) doRequest(method string, path string, body []byte) ([]byte, error) { b := bytes.NewBuffer(body) req, err := http.NewRequest(method, client.URL.String()+path, b) diff --git a/utils.go b/utils.go new file mode 100644 index 0000000000000..64959ff3027ef --- /dev/null +++ b/utils.go @@ -0,0 +1,23 @@ +package dockerclient + +import ( + "net" + "net/http" + "net/url" +) + +func newHTTPClient(u *url.URL) *http.Client { + httpTransport := &http.Transport{} + if u.Scheme == "unix" { + socketPath := u.Path + unixDial := func(proto string, addr string) (net.Conn, error) { + return net.Dial("unix", socketPath) + } + httpTransport.Dial = unixDial + // Override the main URL object so the HTTP lib won't complain + u.Scheme = "http" + u.Host = "unix.sock" + } + u.Path = "" + return &http.Client{Transport: httpTransport} +} From 33ecf7a8a863ad6ce1a65715374e6cfae3e4659c Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Sun, 20 Apr 2014 11:20:03 -0700 Subject: [PATCH 2/2] Refactor events to use the stream and not buffer --- dockerclient.go | 61 ++++++++++++++++++---------------------------- examples/events.go | 32 ++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 37 deletions(-) create mode 100644 examples/events.go diff --git a/dockerclient.go b/dockerclient.go index 2ed27c9e961a8..73fafbb502c8b 100644 --- a/dockerclient.go +++ b/dockerclient.go @@ -5,10 +5,10 @@ import ( "encoding/json" "fmt" "io/ioutil" + "log" "net/http" "net/url" "sync/atomic" - "time" ) type DockerClient struct { @@ -17,6 +17,8 @@ type DockerClient struct { monitorEvents int32 } +type Callback func(*Event, ...interface{}) + func NewDockerClient(daemonUrl string) (*DockerClient, error) { u, err := url.Parse(daemonUrl) if err != nil { @@ -133,44 +135,29 @@ func (client *DockerClient) KillContainer(id string) error { return nil } -func (client *DockerClient) StartMonitorEvents(cb func(*Event, ...interface{}), args ...interface{}) { +func (client *DockerClient) StartMonitorEvents(cb Callback, args ...interface{}) { atomic.StoreInt32(&client.monitorEvents, 1) - wait := 100 * time.Millisecond - buffer := make([]byte, 4096) - var running int32 = 1 - go func() { - for running > 0 { - running = atomic.LoadInt32(&client.monitorEvents) - if running == 0 { - break - } - uri := client.URL.String() + "/v1.10/events" - resp, err := client.HTTPClient.Get(uri) - if err != nil { - time.Sleep(wait) - continue - } - if resp.StatusCode >= 300 { - resp.Body.Close() - time.Sleep(wait) - continue - } - for { - nBytes, err := resp.Body.Read(buffer) - if err != nil { - resp.Body.Close() - time.Sleep(wait) - break - } - event := &Event{} - err = json.Unmarshal(buffer[:nBytes], event) - if err == nil { - cb(event, args...) - } - } - time.Sleep(wait) + go client.getEvents(cb, args...) +} + +func (client *DockerClient) getEvents(cb Callback, args ...interface{}) { + uri := client.URL.String() + "/v1.10/events" + resp, err := client.HTTPClient.Get(uri) + if err != nil { + log.Println(err) + return + } + defer resp.Body.Close() + + dec := json.NewDecoder(resp.Body) + for atomic.LoadInt32(&client.monitorEvents) > 0 { + var event *Event + if err := dec.Decode(&event); err != nil { + log.Println(err) + return } - }() + cb(event, args...) + } } func (client *DockerClient) StopAllMonitorEvents() { diff --git a/examples/events.go b/examples/events.go new file mode 100644 index 0000000000000..d4ba73e5b6713 --- /dev/null +++ b/examples/events.go @@ -0,0 +1,32 @@ +package main + +import ( + "github.com/samalba/dockerclient" + "log" + "os" + "os/signal" + "syscall" +) + +func eventCallback(e *dockerclient.Event, args ...interface{}) { + log.Println(e) +} + +func waitForInterrupt() { + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) + for _ = range sigChan { + os.Exit(0) + } +} + +func main() { + docker, err := dockerclient.NewDockerClient(os.Getenv("DOCKER_HOST")) + if err != nil { + log.Fatal(err) + } + + docker.StartMonitorEvents(eventCallback) + + waitForInterrupt() +}