Use libkermit for integration test

Using the compose package for starting and stopping project.
This commit is contained in:
Vincent Demeester 2016-03-27 19:58:08 +02:00
parent 50f09c8e4d
commit 87bad71bec
5 changed files with 46 additions and 160 deletions

10
glide.lock generated
View file

@ -1,5 +1,5 @@
hash: 6f5b6e92b805fed0bb6a5bfe411b5ca501bc04accebeb739cec039e6499271e2 hash: 7734b691c46b399a06cdcaa5d7feb77ea32e350cd4ff04dcbc73c06ef22468e6
updated: 2016-03-16T13:22:21.850972237+01:00 updated: 2016-03-27T19:57:17.213688266+02:00
imports: imports:
- name: github.com/alecthomas/template - name: github.com/alecthomas/template
version: b867cc6ab45cece8143cfcc6fc9c77cf3f2c23c0 version: b867cc6ab45cece8143cfcc6fc9c77cf3f2c23c0
@ -79,7 +79,7 @@ imports:
- utils - utils
- volume - volume
- name: github.com/docker/libcompose - name: github.com/docker/libcompose
version: d3089811c119a211469a9cc93caea684d937e5d3 version: e290a513ba909ca3afefd5cd611f3a3fe56f6a3a
subpackages: subpackages:
- docker - docker
- logger - logger
@ -114,10 +114,10 @@ imports:
- external/github.com/Sirupsen/logrus - external/github.com/Sirupsen/logrus
- external/github.com/docker/docker/pkg/idtools - external/github.com/docker/docker/pkg/idtools
- external/github.com/docker/docker/pkg/ioutils - external/github.com/docker/docker/pkg/ioutils
- external/github.com/docker/docker/pkg/longpath
- external/github.com/docker/docker/pkg/pools - external/github.com/docker/docker/pkg/pools
- external/github.com/docker/docker/pkg/promise - external/github.com/docker/docker/pkg/promise
- external/github.com/docker/docker/pkg/system - external/github.com/docker/docker/pkg/system
- external/github.com/docker/docker/pkg/longpath
- external/github.com/opencontainers/runc/libcontainer/user - external/github.com/opencontainers/runc/libcontainer/user
- external/golang.org/x/sys/unix - external/golang.org/x/sys/unix
- external/golang.org/x/net/context - external/golang.org/x/net/context
@ -217,6 +217,8 @@ imports:
version: 54ed61c2b47e263ae2f01b86837b0c4bd1da28e8 version: 54ed61c2b47e263ae2f01b86837b0c4bd1da28e8
- name: github.com/unrolled/render - name: github.com/unrolled/render
version: 26b4e3aac686940fe29521545afad9966ddfc80c version: 26b4e3aac686940fe29521545afad9966ddfc80c
- name: github.com/vdemeester/libkermit
version: 01a5399bdbd3312916c9fa4848108fbc81fe88d8
- name: github.com/vdemeester/shakers - name: github.com/vdemeester/shakers
version: 8fe734f75f3a70b651cbfbf8a55a009da09e8dc5 version: 8fe734f75f3a70b651cbfbf8a55a009da09e8dc5
- name: github.com/vulcand/oxy - name: github.com/vulcand/oxy

View file

@ -124,7 +124,7 @@ import:
- package: gopkg.in/alecthomas/kingpin.v2 - package: gopkg.in/alecthomas/kingpin.v2
ref: 639879d6110b1b0409410c7b737ef0bb18325038 ref: 639879d6110b1b0409410c7b737ef0bb18325038
- package: github.com/docker/libcompose - package: github.com/docker/libcompose
ref: d3089811c119a211469a9cc93caea684d937e5d3 ref: e290a513ba909ca3afefd5cd611f3a3fe56f6a3a
subpackages: subpackages:
- docker - docker
- logger - logger
@ -165,3 +165,5 @@ import:
- package: github.com/vulcand/vulcand/plugin/rewrite - package: github.com/vulcand/vulcand/plugin/rewrite
- package: github.com/stretchr/testify/mock - package: github.com/stretchr/testify/mock
- package: github.com/xenolf/lego - package: github.com/xenolf/lego
- package: github.com/vdemeester/libkermit
ref: 01a5399bdbd3312916c9fa4848108fbc81fe88d8

View file

@ -1,16 +1,14 @@
package main package main
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"os/exec" "os/exec"
"time" "time"
"github.com/docker/docker/opts"
"github.com/fsouza/go-dockerclient"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
docker "github.com/vdemeester/libkermit/docker"
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1" check "gopkg.in/check.v1"
) )
@ -20,29 +18,19 @@ type ConsulCatalogSuite struct {
BaseSuite BaseSuite
consulIP string consulIP string
consulClient *api.Client consulClient *api.Client
dockerClient *docker.Client project *docker.Project
}
func (s *ConsulCatalogSuite) GetContainer(name string) (*docker.Container, error) {
return s.dockerClient.InspectContainer(name)
} }
func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) { func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) {
dockerHost := os.Getenv("DOCKER_HOST") project, err := docker.NewProjectFromEnv()
if dockerHost == "" { c.Assert(err, checker.IsNil, check.Commentf("Error while creating docker project"))
// FIXME Handle windows -- see if dockerClient already handle that or not s.project = project
dockerHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket)
}
// Make sure we can speak to docker
dockerClient, err := docker.NewClient(dockerHost)
c.Assert(err, checker.IsNil, check.Commentf("Error connecting to docker daemon"))
s.dockerClient = dockerClient
s.createComposeProject(c, "consul_catalog") s.createComposeProject(c, "consul_catalog")
err = s.composeProject.Up() err = s.composeProject.Start()
c.Assert(err, checker.IsNil, check.Commentf("Error starting project")) c.Assert(err, checker.IsNil, check.Commentf("Error starting project"))
consul, err := s.GetContainer("integration-test-consul_catalog_consul_1") consul, err := s.project.Inspect("integration-test-consul_catalog_consul_1")
c.Assert(err, checker.IsNil, check.Commentf("Error finding consul container")) c.Assert(err, checker.IsNil, check.Commentf("Error finding consul container"))
s.consulIP = consul.NetworkSettings.IPAddress s.consulIP = consul.NetworkSettings.IPAddress
@ -110,7 +98,7 @@ func (s *ConsulCatalogSuite) TestSingleService(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer cmd.Process.Kill() defer cmd.Process.Kill()
nginx, err := s.GetContainer("integration-test-consul_catalog_nginx_1") nginx, err := s.project.Inspect("integration-test-consul_catalog_nginx_1")
c.Assert(err, checker.IsNil, check.Commentf("Error finding nginx container")) c.Assert(err, checker.IsNil, check.Commentf("Error finding nginx container"))
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80) err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80)

View file

@ -7,11 +7,12 @@ import (
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"strings"
"time" "time"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/namesgenerator" "github.com/docker/docker/pkg/namesgenerator"
"github.com/fsouza/go-dockerclient" "github.com/vdemeester/libkermit/docker"
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1" check "gopkg.in/check.v1"
) )
@ -31,108 +32,50 @@ var (
// Docker test suites // Docker test suites
type DockerSuite struct { type DockerSuite struct {
BaseSuite BaseSuite
client *docker.Client project *docker.Project
} }
func (s *DockerSuite) startContainer(c *check.C, image string, args ...string) string { func (s *DockerSuite) startContainer(c *check.C, image string, args ...string) string {
return s.startContainerWithConfig(c, docker.CreateContainerOptions{ return s.startContainerWithConfig(c, image, docker.ContainerConfig{
Config: &docker.Config{
Image: image,
Cmd: args, Cmd: args,
},
}) })
} }
func (s *DockerSuite) startContainerWithLabels(c *check.C, image string, labels map[string]string, args ...string) string { func (s *DockerSuite) startContainerWithLabels(c *check.C, image string, labels map[string]string, args ...string) string {
return s.startContainerWithConfig(c, docker.CreateContainerOptions{ return s.startContainerWithConfig(c, image, docker.ContainerConfig{
Config: &docker.Config{
Image: image,
Cmd: args, Cmd: args,
Labels: labels, Labels: labels,
},
}) })
} }
func (s *DockerSuite) startContainerWithConfig(c *check.C, config docker.CreateContainerOptions) string { func (s *DockerSuite) startContainerWithConfig(c *check.C, image string, config docker.ContainerConfig) string {
if config.Name == "" { if config.Name == "" {
config.Name = namesgenerator.GetRandomName(10) config.Name = namesgenerator.GetRandomName(10)
} }
if config.Config.Labels == nil {
config.Config.Labels = map[string]string{}
}
config.Config.Labels[TestLabel] = "true"
container, err := s.client.CreateContainer(config) container, err := s.project.StartWithConfig(image, config)
c.Assert(err, checker.IsNil, check.Commentf("Error creating a container using config %v", config)) c.Assert(err, checker.IsNil, check.Commentf("Error starting a container using config %v", config))
err = s.client.StartContainer(container.ID, &docker.HostConfig{}) // FIXME(vdemeester) this is ugly (it's because of the / in front of the name in docker..)
c.Assert(err, checker.IsNil, check.Commentf("Error starting container %v", container)) return strings.SplitAfter(container.Name, "/")[1]
return container.Name
} }
func (s *DockerSuite) SetUpSuite(c *check.C) { func (s *DockerSuite) SetUpSuite(c *check.C) {
dockerHost := os.Getenv("DOCKER_HOST") project, err := docker.NewProjectFromEnv()
if dockerHost == "" { c.Assert(err, checker.IsNil, check.Commentf("Error while creating docker project"))
// FIXME Handle windows -- see if dockerClient already handle that or not s.project = project
dockerHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket)
}
// Make sure we can speak to docker
dockerClient, err := docker.NewClient(dockerHost)
c.Assert(err, checker.IsNil, check.Commentf("Error connecting to docker daemon"))
s.client = dockerClient
c.Assert(s.client.Ping(), checker.IsNil)
// Pull required images // Pull required images
for repository, tag := range RequiredImages { for repository, tag := range RequiredImages {
image := fmt.Sprintf("%s:%s", repository, tag) image := fmt.Sprintf("%s:%s", repository, tag)
_, err := s.client.InspectImage(image) s.project.Pull(image)
if err != nil {
if err != docker.ErrNoSuchImage {
c.Fatalf("Error while inspect image %s", image)
}
err = s.client.PullImage(docker.PullImageOptions{
Repository: repository,
Tag: tag,
}, docker.AuthConfiguration{})
c.Assert(err, checker.IsNil, check.Commentf("Error while pulling image %s", image)) c.Assert(err, checker.IsNil, check.Commentf("Error while pulling image %s", image))
} }
} }
}
func (s *DockerSuite) cleanContainers(c *check.C) {
// Clean the mess, a.k.a. the running containers with the right label
containerList, err := s.client.ListContainers(docker.ListContainersOptions{
Filters: map[string][]string{
"label": {fmt.Sprintf("%s=true", TestLabel)},
},
})
c.Assert(err, checker.IsNil, check.Commentf("Error listing containers started by traefik"))
for _, container := range containerList {
err = s.client.KillContainer(docker.KillContainerOptions{
ID: container.ID,
})
c.Assert(err, checker.IsNil, check.Commentf("Error killing container %v", container))
if os.Getenv("CIRCLECI") == "" {
// On circleci, we won't delete them — it errors out for now >_<
err = s.client.RemoveContainer(docker.RemoveContainerOptions{
ID: container.ID,
RemoveVolumes: true,
})
c.Assert(err, checker.IsNil, check.Commentf("Error removing container %v", container))
}
}
}
func (s *DockerSuite) TearDownTest(c *check.C) { func (s *DockerSuite) TearDownTest(c *check.C) {
s.cleanContainers(c) err := s.project.Clean(os.Getenv("CIRCLECI") != "")
} c.Assert(err, checker.IsNil, check.Commentf("Error while cleaning containers"))
func (s *DockerSuite) TearDownSuite(c *check.C) {
// Call cleanContainers, just in case (?)
// s.cleanContainers(c)
} }
func (s *DockerSuite) TestSimpleConfiguration(c *check.C) { func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {

View file

@ -11,8 +11,7 @@ import (
"text/template" "text/template"
"github.com/containous/traefik/integration/utils" "github.com/containous/traefik/integration/utils"
"github.com/docker/libcompose/docker" "github.com/vdemeester/libkermit/compose"
"github.com/docker/libcompose/project"
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1" check "gopkg.in/check.v1"
@ -36,71 +35,23 @@ func init() {
var traefikBinary = "../dist/traefik" var traefikBinary = "../dist/traefik"
type BaseSuite struct { type BaseSuite struct {
composeProject *project.Project composeProject *compose.Project
listenChan chan project.Event
started chan bool
stopped chan bool
deleted chan bool
} }
func (s *BaseSuite) TearDownSuite(c *check.C) { func (s *BaseSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project // shutdown and delete compose project
if s.composeProject != nil { if s.composeProject != nil {
s.composeProject.Down() err := s.composeProject.Stop()
<-s.stopped c.Assert(err, checker.IsNil)
defer close(s.stopped)
s.composeProject.Delete()
<-s.deleted
defer close(s.deleted)
} }
} }
func (s *BaseSuite) createComposeProject(c *check.C, name string) { func (s *BaseSuite) createComposeProject(c *check.C, name string) {
composeProject, err := docker.NewProject(&docker.Context{ projectName := fmt.Sprintf("integration-test-%s", name)
Context: project.Context{ composeFile := fmt.Sprintf("resources/compose/%s.yml", name)
ComposeFiles: []string{ composeProject, err := compose.CreateProject(projectName, composeFile)
fmt.Sprintf("resources/compose/%s.yml", name),
},
ProjectName: fmt.Sprintf("integration-test-%s", name),
},
})
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
s.composeProject = composeProject s.composeProject = composeProject
err = composeProject.Create()
c.Assert(err, checker.IsNil)
s.started = make(chan bool)
s.stopped = make(chan bool)
s.deleted = make(chan bool)
s.listenChan = make(chan project.Event)
go s.startListening(c)
composeProject.AddListener(s.listenChan)
err = composeProject.Start()
c.Assert(err, checker.IsNil)
// Wait for compose to start
<-s.started
defer close(s.started)
}
func (s *BaseSuite) startListening(c *check.C) {
for event := range s.listenChan {
// FIXME Add a timeout on event ?
if event.EventType == project.EventProjectStartDone {
s.started <- true
}
if event.EventType == project.EventProjectDownDone {
s.stopped <- true
}
if event.EventType == project.EventProjectDeleteDone {
s.deleted <- true
}
}
} }
func (s *BaseSuite) traefikCmd(c *check.C, args ...string) (*exec.Cmd, string) { func (s *BaseSuite) traefikCmd(c *check.C, args ...string) (*exec.Cmd, string) {