summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--pkg/api/handlers/libpod/healthcheck.go24
-rw-r--r--pkg/api/server/register_healthcheck.go25
-rw-r--r--pkg/api/server/swagger.go9
-rw-r--r--pkg/bindings/containers/healthcheck.go6
-rw-r--r--pkg/bindings/test/containers_test.go45
-rw-r--r--vendor/github.com/fsnotify/fsnotify/.editorconfig9
-rw-r--r--vendor/github.com/fsnotify/fsnotify/.gitattributes1
-rw-r--r--vendor/github.com/fsnotify/fsnotify/.travis.yml20
-rw-r--r--vendor/github.com/fsnotify/fsnotify/LICENSE2
-rw-r--r--vendor/github.com/fsnotify/fsnotify/README.md71
-rw-r--r--vendor/github.com/fsnotify/fsnotify/fsnotify.go4
-rw-r--r--vendor/github.com/fsnotify/fsnotify/go.mod5
-rw-r--r--vendor/github.com/fsnotify/fsnotify/go.sum2
-rw-r--r--vendor/github.com/fsnotify/fsnotify/inotify_poller.go4
-rw-r--r--vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go2
-rw-r--r--vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go2
-rw-r--r--vendor/modules.txt2
19 files changed, 207 insertions, 31 deletions
diff --git a/go.mod b/go.mod
index ec5d599ee..56b0baf0e 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.4.0
github.com/etcd-io/bbolt v1.3.3
- github.com/fsnotify/fsnotify v1.4.7
+ github.com/fsnotify/fsnotify v1.4.9
github.com/ghodss/yaml v1.0.0
github.com/godbus/dbus/v5 v5.0.3
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
diff --git a/go.sum b/go.sum
index 61fdc20d7..ec6329366 100644
--- a/go.sum
+++ b/go.sum
@@ -150,6 +150,8 @@ github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsouza/go-dockerclient v1.6.3 h1:VS/I3mxieZVIeaWXd57JKvSjheELafUJYtblGg75RIQ=
github.com/fsouza/go-dockerclient v1.6.3/go.mod h1:OiSy/IhZIF+zheikZkXK7LVpGzxWchJPJKGWhBqOK4M=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
@@ -549,6 +551,7 @@ golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/pkg/api/handlers/libpod/healthcheck.go b/pkg/api/handlers/libpod/healthcheck.go
index 6c74500b9..6eb2ab0e3 100644
--- a/pkg/api/handlers/libpod/healthcheck.go
+++ b/pkg/api/handlers/libpod/healthcheck.go
@@ -14,8 +14,30 @@ func RunHealthCheck(w http.ResponseWriter, r *http.Request) {
if err != nil {
if status == libpod.HealthCheckContainerNotFound {
utils.ContainerNotFound(w, name, err)
+ return
}
+ if status == libpod.HealthCheckNotDefined {
+ utils.Error(w, "no healthcheck defined", http.StatusConflict, err)
+ return
+ }
+ if status == libpod.HealthCheckContainerStopped {
+ utils.Error(w, "container not running", http.StatusConflict, err)
+ return
+ }
+ utils.InternalServerError(w, err)
+ return
+ }
+ ctr, err := runtime.LookupContainer(name)
+ if err != nil {
utils.InternalServerError(w, err)
+ return
}
- utils.WriteResponse(w, http.StatusOK, status)
+
+ hcLog, err := ctr.GetHealthCheckLog()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, hcLog)
}
diff --git a/pkg/api/server/register_healthcheck.go b/pkg/api/server/register_healthcheck.go
index 5466e2905..69aa5bbfb 100644
--- a/pkg/api/server/register_healthcheck.go
+++ b/pkg/api/server/register_healthcheck.go
@@ -8,6 +8,29 @@ import (
)
func (s *APIServer) registerHealthCheckHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/libpod/containers/{name}/runhealthcheck"), s.APIHandler(libpod.RunHealthCheck)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/containers/{name:.*}/healthcheck libpod libpodRunHealthCheck
+ // ---
+ // tags:
+ // - containers
+ // summary: Run a container's healthcheck
+ // description: Execute the defined healthcheck and return information about the results
+ // parameters:
+ // - in: path
+ // name: name:.*
+ // type: string
+ // required: true
+ // description: the name or ID of the container
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/HealthcheckRun"
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // description: container has no healthcheck or is not running
+ // 500:
+ // $ref: '#/responses/InternalError'
+ r.Handle(VersionedPath("/libpod/containers/{name:.*}/healthcheck"), s.APIHandler(libpod.RunHealthCheck)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 011196e5a..e3c991d6d 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -156,3 +156,12 @@ type swagVolumeListResponse struct {
// in:body
Body []libpod.Volume
}
+
+// Healthcheck
+// swagger:response HealthcheckRun
+type swagHealthCheckRunResponse struct {
+ // in:body
+ Body struct {
+ libpod.HealthCheckResults
+ }
+}
diff --git a/pkg/bindings/containers/healthcheck.go b/pkg/bindings/containers/healthcheck.go
index 3f94fad01..85cc2814c 100644
--- a/pkg/bindings/containers/healthcheck.go
+++ b/pkg/bindings/containers/healthcheck.go
@@ -10,15 +10,15 @@ import (
// RunHealthCheck executes the container's healthcheck and returns the health status of the
// container.
-func RunHealthCheck(ctx context.Context, nameOrID string) (*libpod.HealthCheckStatus, error) {
+func RunHealthCheck(ctx context.Context, nameOrID string) (*libpod.HealthCheckResults, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
var (
- status libpod.HealthCheckStatus
+ status libpod.HealthCheckResults
)
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/runhealthcheck", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/healthcheck", nil, nameOrID)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index e7ef620d4..34a9c3136 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -312,4 +312,49 @@ var _ = Describe("Podman containers ", func() {
Expect(exitCode).To(BeNumerically("==", -1))
})
+ It("run healthcheck", func() {
+ bt.runPodman([]string{"run", "-d", "--name", "hc", "--health-interval", "disable", "--health-retries", "2", "--health-cmd", "ls / || exit 1", alpine.name, "top"})
+
+ // bogus name should result in 404
+ _, err := containers.RunHealthCheck(bt.conn, "foobar")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ // a container that has no healthcheck should be a 409
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ _, err = containers.RunHealthCheck(bt.conn, name)
+ Expect(err).ToNot(BeNil())
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusConflict))
+
+ // TODO for the life of me, i cannot get this to work. maybe another set
+ // of eyes will
+ // successful healthcheck
+ //status := "healthy"
+ //for i:=0; i < 10; i++ {
+ // result, err := containers.RunHealthCheck(connText, "hc")
+ // Expect(err).To(BeNil())
+ // if result.Status != "healthy" {
+ // fmt.Println("Healthcheck container still starting, retrying in 1 second")
+ // time.Sleep(1 * time.Second)
+ // continue
+ // }
+ // status = result.Status
+ // break
+ //}
+ //Expect(status).To(Equal("healthy"))
+
+ // TODO enable this when wait is working
+ // healthcheck on a stopped container should be a 409
+ //err = containers.Stop(connText, "hc", nil)
+ //Expect(err).To(BeNil())
+ //_, err = containers.Wait(connText, "hc")
+ //Expect(err).To(BeNil())
+ //_, err = containers.RunHealthCheck(connText, "hc")
+ //code, _ = bindings.CheckResponseCode(err)
+ //Expect(code).To(BeNumerically("==", http.StatusConflict))
+ })
+
})
diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/fsnotify/fsnotify/.editorconfig
index ba49e3c23..fad895851 100644
--- a/vendor/github.com/fsnotify/fsnotify/.editorconfig
+++ b/vendor/github.com/fsnotify/fsnotify/.editorconfig
@@ -1,5 +1,12 @@
root = true
-[*]
+[*.go]
indent_style = tab
indent_size = 4
+insert_final_newline = true
+
+[*.{yml,yaml}]
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes
new file mode 100644
index 000000000..32f1001be
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/.gitattributes
@@ -0,0 +1 @@
+go.sum linguist-generated
diff --git a/vendor/github.com/fsnotify/fsnotify/.travis.yml b/vendor/github.com/fsnotify/fsnotify/.travis.yml
index 981d1bb81..a9c30165c 100644
--- a/vendor/github.com/fsnotify/fsnotify/.travis.yml
+++ b/vendor/github.com/fsnotify/fsnotify/.travis.yml
@@ -2,29 +2,35 @@ sudo: false
language: go
go:
- - 1.8.x
- - 1.9.x
- - tip
+ - "stable"
+ - "1.11.x"
+ - "1.10.x"
+ - "1.9.x"
matrix:
+ include:
+ - go: "stable"
+ env: GOLINT=true
allow_failures:
- go: tip
fast_finish: true
-before_script:
- - go get -u github.com/golang/lint/golint
+
+before_install:
+ - if [ ! -z "${GOLINT}" ]; then go get -u golang.org/x/lint/golint; fi
script:
- - go test -v --race ./...
+ - go test --race ./...
after_script:
- test -z "$(gofmt -s -l -w . | tee /dev/stderr)"
- - test -z "$(golint ./... | tee /dev/stderr)"
+ - if [ ! -z "${GOLINT}" ]; then echo running golint; golint --set_exit_status ./...; else echo skipping golint; fi
- go vet ./...
os:
- linux
- osx
+ - windows
notifications:
email: false
diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE
index f21e54080..e180c8fb0 100644
--- a/vendor/github.com/fsnotify/fsnotify/LICENSE
+++ b/vendor/github.com/fsnotify/fsnotify/LICENSE
@@ -1,5 +1,5 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
-Copyright (c) 2012 fsnotify Authors. All rights reserved.
+Copyright (c) 2012-2019 fsnotify Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md
index 399320741..b2629e522 100644
--- a/vendor/github.com/fsnotify/fsnotify/README.md
+++ b/vendor/github.com/fsnotify/fsnotify/README.md
@@ -10,16 +10,16 @@ go get -u golang.org/x/sys/...
Cross platform: Windows, Linux, BSD and macOS.
-|Adapter |OS |Status |
-|----------|----------|----------|
-|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)|
-|kqueue |BSD, macOS, iOS\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)|
-|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)|
-|FSEvents |macOS |[Planned](https://github.com/fsnotify/fsnotify/issues/11)|
-|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)|
-|fanotify |Linux 2.6.37+ | |
-|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)|
-|Polling |*All* |[Maybe](https://github.com/fsnotify/fsnotify/issues/9)|
+| Adapter | OS | Status |
+| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| inotify | Linux 2.6.27 or later, Android\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) |
+| kqueue | BSD, macOS, iOS\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) |
+| ReadDirectoryChangesW | Windows | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) |
+| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) |
+| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) |
+| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) |
+| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) |
+| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) |
\* Android and iOS are untested.
@@ -33,6 +33,53 @@ All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based o
Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`.
+## Usage
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/fsnotify/fsnotify"
+)
+
+func main() {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer watcher.Close()
+
+ done := make(chan bool)
+ go func() {
+ for {
+ select {
+ case event, ok := <-watcher.Events:
+ if !ok {
+ return
+ }
+ log.Println("event:", event)
+ if event.Op&fsnotify.Write == fsnotify.Write {
+ log.Println("modified file:", event.Name)
+ }
+ case err, ok := <-watcher.Errors:
+ if !ok {
+ return
+ }
+ log.Println("error:", err)
+ }
+ }
+ }()
+
+ err = watcher.Add("/tmp/foo")
+ if err != nil {
+ log.Fatal(err)
+ }
+ <-done
+}
+```
+
## Contributing
Please refer to [CONTRIBUTING][] before opening an issue or pull request.
@@ -65,6 +112,10 @@ There are OS-specific limits as to how many watches can be created:
* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error.
* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error.
+**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?**
+
+fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications.
+
[#62]: https://github.com/howeyc/fsnotify/issues/62
[#18]: https://github.com/fsnotify/fsnotify/issues/18
[#11]: https://github.com/fsnotify/fsnotify/issues/11
diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go
index 190bf0de5..89cab046d 100644
--- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go
+++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go
@@ -63,4 +63,6 @@ func (e Event) String() string {
}
// Common errors that can be reported by a watcher
-var ErrEventOverflow = errors.New("fsnotify queue overflow")
+var (
+ ErrEventOverflow = errors.New("fsnotify queue overflow")
+)
diff --git a/vendor/github.com/fsnotify/fsnotify/go.mod b/vendor/github.com/fsnotify/fsnotify/go.mod
new file mode 100644
index 000000000..ff11e13f2
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/go.mod
@@ -0,0 +1,5 @@
+module github.com/fsnotify/fsnotify
+
+go 1.13
+
+require golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9
diff --git a/vendor/github.com/fsnotify/fsnotify/go.sum b/vendor/github.com/fsnotify/fsnotify/go.sum
new file mode 100644
index 000000000..f60af9855
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go
index cc7db4b22..b33f2b4d4 100644
--- a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go
+++ b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go
@@ -40,12 +40,12 @@ func newFdPoller(fd int) (*fdPoller, error) {
poller.fd = fd
// Create epoll fd
- poller.epfd, errno = unix.EpollCreate1(0)
+ poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC)
if poller.epfd == -1 {
return nil, errno
}
// Create pipe; pipe[0] is the read end, pipe[1] the write end.
- errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK)
+ errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC)
if errno != nil {
return nil, errno
}
diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
index 7d8de1451..2306c4620 100644
--- a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
+++ b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
@@ -8,4 +8,4 @@ package fsnotify
import "golang.org/x/sys/unix"
-const openMode = unix.O_NONBLOCK | unix.O_RDONLY
+const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC
diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
index 9139e1716..870c4d6d1 100644
--- a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
+++ b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
@@ -9,4 +9,4 @@ package fsnotify
import "golang.org/x/sys/unix"
// note: this constant is not defined on BSD
-const openMode = unix.O_EVTONLY
+const openMode = unix.O_EVTONLY | unix.O_CLOEXEC
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ad8ebb4e4..e5ee01a4e 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -262,7 +262,7 @@ github.com/docker/spdystream
github.com/docker/spdystream/spdy
# github.com/etcd-io/bbolt v1.3.3
github.com/etcd-io/bbolt
-# github.com/fsnotify/fsnotify v1.4.7
+# github.com/fsnotify/fsnotify v1.4.9
github.com/fsnotify/fsnotify
# github.com/fsouza/go-dockerclient v1.6.3
github.com/fsouza/go-dockerclient