From 8e30f82d0325affcc935ea3256d66091a4f789e5 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Wed, 3 Oct 2018 12:59:35 +0200 Subject: [PATCH] upd(vendor): import dockertest --- Gopkg.lock | 11 +- .../titpetric/dockertest/.gitignore | 24 ++++ .../titpetric/dockertest/.travis.yml | 10 ++ .../github.com/titpetric/dockertest/LICENSE | 21 +++ .../github.com/titpetric/dockertest/README.md | 69 ++++++++++ .../titpetric/dockertest/container.go | 128 ++++++++++++++++++ 6 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 vendor/github.com/titpetric/dockertest/.gitignore create mode 100644 vendor/github.com/titpetric/dockertest/.travis.yml create mode 100644 vendor/github.com/titpetric/dockertest/LICENSE create mode 100644 vendor/github.com/titpetric/dockertest/README.md create mode 100644 vendor/github.com/titpetric/dockertest/container.go diff --git a/Gopkg.lock b/Gopkg.lock index d3aa84fcf..8d77f4eae 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -292,6 +292,14 @@ revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd" version = "v1.1.2" +[[projects]] + branch = "master" + digest = "1:867c2915fb252b272b86235c13cffb60627ecc35e1f334c77aaf7f154fbba352" + name = "github.com/titpetric/dockertest" + packages = ["."] + pruneopts = "UT" + revision = "3cd6aeb62a5fe526e54b1af7c05c5c9a2eac16dd" + [[projects]] branch = "master" digest = "1:da5d4db2177186b9dce6300624895ec6401ff49197568865a3b850fd767b590f" @@ -344,7 +352,7 @@ "trace", ] pruneopts = "UT" - revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de" + revision = "f5e5bdd778241bfefa8627f7124c39cd6ad8d74f" [[projects]] branch = "master" @@ -489,6 +497,7 @@ "github.com/prometheus/client_golang/prometheus", "github.com/rakyll/statik/fs", "github.com/spf13/afero", + "github.com/titpetric/dockertest", "github.com/titpetric/factory", "github.com/titpetric/factory/resputil", "golang.org/x/crypto/bcrypt", diff --git a/vendor/github.com/titpetric/dockertest/.gitignore b/vendor/github.com/titpetric/dockertest/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/titpetric/dockertest/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/titpetric/dockertest/.travis.yml b/vendor/github.com/titpetric/dockertest/.travis.yml new file mode 100644 index 000000000..69217ca9a --- /dev/null +++ b/vendor/github.com/titpetric/dockertest/.travis.yml @@ -0,0 +1,10 @@ +language: go +go: + - 1.8 + +sudo: required +services: + - docker + +script: + - go test -race -v ./... diff --git a/vendor/github.com/titpetric/dockertest/LICENSE b/vendor/github.com/titpetric/dockertest/LICENSE new file mode 100644 index 000000000..156ab5b93 --- /dev/null +++ b/vendor/github.com/titpetric/dockertest/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Ian Chiles (fortytw2) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/titpetric/dockertest/README.md b/vendor/github.com/titpetric/dockertest/README.md new file mode 100644 index 000000000..f586aa6d3 --- /dev/null +++ b/vendor/github.com/titpetric/dockertest/README.md @@ -0,0 +1,69 @@ +# Dockertest [![Build Status](https://travis-ci.org/fortytw2/dockertest.svg?branch=master)](https://travis-ci.org/fortytw2/dockertest) + +`dockertest` allows you to quickly and easily test database interactions by +creating and destroying databases within your tests using `docker`. + +It works by controlling the docker daemon running locally with `exec.Command`. +The flow is as follows -> + +1. find a free port on the local machine +2. launch docker container and bind that port +3. wait until the container needs to be shutdown + +`dockertest` is inspired by https://divan.github.io/posts/integration_testing/ +and https://github.com/ory-am/dockertest - however, it does not add 300k loc of dependencies (guesstimated) to your project. See https://github.com/fsouza/go-dockerclient/issues/599 for more info on this. + +# Installation + +```sh +go get -u github.com/fortytw2/dockertest +``` + +currently the tests depend on `github.com/lib/pq` + +# How good is it? + +Currently the manipulation of the docker daemon is somewhat fragile, as it depends on `exec.Command` and a well placed `time.Sleep` for shutdown. In an +ideal world, this would use the docker api via the docker socket directly, +but it currently works well enough for now. Contributions welcome + +# Usage + +Postgres example copied from `github.com/fortytw2/hydrocarbon` + +```go +func TestDBBits(t *testing.T) { + container, err := dockertest.RunContainer("postgres:alpine", "5432", func(addr string) error { + db, err := sql.Open("postgres", "postgres://postgres:postgres@"+addr+"?sslmode=disable") + if err != nil { + return err + } + + return db.Ping() + }) + defer container.Shutdown() + if err != nil { + t.Fatalf("could not start postgres, %s", err) + } + + db, err := sql.Open("postgres", "postgres://postgres:postgres@" + container.Addr + "?sslmode=disable") + if err != nil { + t.Fatal(err) + } + + // run tests on the db, etc +} +``` + +It should be trivial to adapt the above bits to work just as well from a +`TestMain` function, if you want to avoid running a new container for each +individual test function - subtests also help here. + +### Docker-machine host + +Note that dockertest will give priority to the `DOCKER_MACHINE_NAME` when looking for your container address and will fallback to `localhost` if it fails to find it. + +# License + +MIT, see LICENSE + diff --git a/vendor/github.com/titpetric/dockertest/container.go b/vendor/github.com/titpetric/dockertest/container.go new file mode 100644 index 000000000..ee73f62c0 --- /dev/null +++ b/vendor/github.com/titpetric/dockertest/container.go @@ -0,0 +1,128 @@ +package dockertest + +import ( + "context" + "fmt" + "net" + "os" + "os/exec" + "strings" + "syscall" + "time" +) + +// A Container is a container inside docker +type Container struct { + Name string + Args []string + Addr string + cmd *exec.Cmd +} + +// Shutdown ends the container +func (c *Container) Shutdown() { + if c != nil { + c.cmd.Process.Signal(syscall.SIGINT) + // Wait till the process exits. + c.cmd.Wait() + } +} + +// Shutdown ends the container +func (c *Container) Terminate() { + if c != nil { + c.cmd.Process.Signal(syscall.SIGTERM) + // Wait till the process exits. + c.cmd.Wait() + } +} + +// RunContainer runs a given docker image and returns a port on which the +// container can be reached +func RunContainer(name string, port string, waitFunc func(addr string) error, args ...string) (*Container, error) { + free := freePort() + host := getHost() + addr := fmt.Sprintf("%s:%d", host, free) + argsFull := append([]string{"run"}, args...) + argsFull = append(argsFull, "-p", fmt.Sprintf("%d:%s", free, port), name) + cmd := exec.Command("docker", argsFull...) + // run this in the background + + err := cmd.Start() + if err != nil { + return nil, fmt.Errorf("could not run container, %s", err) + } + for { + if err := waitFunc(addr); err != nil { + continue + } + time.Sleep(time.Millisecond * 150) + } + + return &Container{ + Name: name, + Addr: addr, + Args: args, + cmd: cmd, + }, nil +} + +// RunContainer runs a given docker image and returns a port on which the +// container can be reached +func RunContainerContext(ctx context.Context, name string, port string, waitFunc func(addr string) error, args ...string) (*Container, error) { + free := freePort() + host := getHost() + addr := fmt.Sprintf("%s:%d", host, free) + argsFull := append([]string{"run"}, args...) + argsFull = append(argsFull, "-p", fmt.Sprintf("%d:%s", free, port), name) + cmd := exec.Command("docker", argsFull...) + // run this in the background + + err := cmd.Start() + if err != nil { + return nil, fmt.Errorf("could not run container, %s", err) + } + + result := &Container{ + Name: name, + Addr: addr, + Args: args, + cmd: cmd, + } + + for { + select { + case <-time.After(time.Millisecond * 150): + if err := waitFunc(addr); err != nil { + continue + } + return result, nil + case <-ctx.Done(): + // we still need to Shutdown cmd + return result, ctx.Err() + } + } +} + +func getHost() string { + out, err := exec.Command("docker-machine", "ip", os.Getenv("DOCKER_MACHINE_NAME")).Output() + if err == nil { + return strings.TrimSpace(string(out[:])) + } + return "localhost" +} + +func freePort() int { + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + panic(err) + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + panic(err) + } + defer l.Close() + + return l.Addr().(*net.TCPAddr).Port +}