[marathon] Fix and extend integration tests.
- Update compose file. - Add integration test for Marathon application deployment.
This commit is contained in:
parent
19a5ba3264
commit
64b8fc52c3
4 changed files with 159 additions and 65 deletions
3
Makefile
3
Makefile
|
@ -8,7 +8,8 @@ TRAEFIK_ENVS := \
|
||||||
-e VERSION \
|
-e VERSION \
|
||||||
-e CODENAME \
|
-e CODENAME \
|
||||||
-e TESTDIRS \
|
-e TESTDIRS \
|
||||||
-e CI
|
-e CI \
|
||||||
|
-e CONTAINER=DOCKER # Indicator for integration tests that we are running inside a container.
|
||||||
|
|
||||||
SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/' | grep -v '^integration/vendor/')
|
SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/' | grep -v '^integration/vendor/')
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
defaultEntryPoints = ["http"]
|
defaultEntryPoints = ["http"]
|
||||||
|
|
||||||
|
logLevel = "DEBUG"
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.http]
|
[entryPoints.http]
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
logLevel = "DEBUG"
|
[web]
|
||||||
|
address = ":9090"
|
||||||
|
|
||||||
[marathon]
|
[marathon]
|
||||||
|
endpoint = "{{.MarathonURL}}"
|
||||||
|
watch = true
|
||||||
|
exposedByDefault = true
|
||||||
|
|
|
@ -1,53 +1,129 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containous/traefik/integration/try"
|
"github.com/containous/traefik/integration/try"
|
||||||
|
"github.com/containous/traefik/types"
|
||||||
|
marathon "github.com/gambol99/go-marathon"
|
||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
checker "github.com/vdemeester/shakers"
|
checker "github.com/vdemeester/shakers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
containerNameMesosSlave = "mesos-slave"
|
||||||
|
containerNameMarathon = "marathon"
|
||||||
|
)
|
||||||
|
|
||||||
// Marathon test suites (using libcompose)
|
// Marathon test suites (using libcompose)
|
||||||
type MarathonSuite struct{ BaseSuite }
|
type MarathonSuite struct {
|
||||||
|
BaseSuite
|
||||||
|
marathonURL string
|
||||||
|
}
|
||||||
|
|
||||||
func (s *MarathonSuite) SetUpSuite(c *check.C) {
|
func (s *MarathonSuite) SetUpSuite(c *check.C) {
|
||||||
s.createComposeProject(c, "marathon")
|
s.createComposeProject(c, "marathon")
|
||||||
s.composeProject.Start(c)
|
s.composeProject.Start(c)
|
||||||
|
|
||||||
// FIXME Doesn't work...
|
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
|
||||||
//// "github.com/gambol99/go-marathon"
|
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
|
||||||
//config := marathon.NewDefaultConfig()
|
s.marathonURL = "http://" + marathonIPAddr + ":8080"
|
||||||
//
|
|
||||||
//marathonClient, err := marathon.NewClient(config)
|
// Wait for Marathon readiness prior to creating the client so that we
|
||||||
//if err != nil {
|
// don't run into the "all cluster members down" state right from the
|
||||||
// c.Fatalf("Error creating Marathon client. %v", err)
|
// start.
|
||||||
//}
|
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||||
//
|
c.Assert(err, checker.IsNil)
|
||||||
//// Wait for Marathon to elect itself leader
|
|
||||||
//err = try.Do(30*time.Second, func() error {
|
// Add entry for Mesos slave container IP address in the hosts file so
|
||||||
// leader, err := marathonClient.Leader()
|
// that Traefik can properly forward traffic.
|
||||||
//
|
// This is necessary as long as we are still using the docker-compose v1
|
||||||
// if err != nil || len(leader) == 0 {
|
// spec. Once we switch to v2 or higher, we can have both the test/builder
|
||||||
// return fmt.Errorf("Leader not found. %v", err)
|
// container and the Mesos slave container join the same custom network and
|
||||||
// }
|
// enjoy DNS-discoverable container host names.
|
||||||
//
|
mesosSlaveIPAddr := s.composeProject.Container(c, containerNameMesosSlave).NetworkSettings.IPAddress
|
||||||
// return nil
|
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
|
||||||
//})
|
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
|
||||||
//
|
c.Assert(err, checker.IsNil)
|
||||||
//c.Assert(err, checker.IsNil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) {
|
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
|
||||||
cmd, _ := s.cmdTraefik(withConfigFile("fixtures/marathon/simple.toml"))
|
// host/IP address mapping if we are running inside a container.
|
||||||
|
func (s *MarathonSuite) extendDockerHostsFile(host, ipAddr string) error {
|
||||||
|
const hostsFile = "/etc/hosts"
|
||||||
|
|
||||||
|
// Determine if the run inside a container. The most reliable way to
|
||||||
|
// do this is to inject an indicator, which we do in terms of an
|
||||||
|
// environment variable.
|
||||||
|
// (See also https://groups.google.com/d/topic/docker-user/JOGE7AnJ3Gw/discussion.)
|
||||||
|
if os.Getenv("CONTAINER") == "DOCKER" {
|
||||||
|
// We are running inside a container -- extend the hosts file.
|
||||||
|
file, err := os.OpenFile(hostsFile, os.O_APPEND|os.O_WRONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if _, err = file.WriteString(fmt.Sprintf("%s\t%s\n", ipAddr, host)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
||||||
|
// Start Traefik.
|
||||||
|
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
|
||||||
|
MarathonURL string
|
||||||
|
}{s.marathonURL})
|
||||||
|
defer os.Remove(file)
|
||||||
|
cmd, output := s.cmdTraefik(withConfigFile(file))
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer cmd.Process.Kill()
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
// TODO validate : run on 80
|
// Wait for Traefik to turn ready.
|
||||||
// Expected a 404 as we did not configure anything
|
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||||
err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
|
||||||
|
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Prepare Marathon client.
|
||||||
|
config := marathon.NewDefaultConfig()
|
||||||
|
config.URL = s.marathonURL
|
||||||
|
client, err := marathon.NewClient(config)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Show the Traefik log if any assertion fails. If the entire test runs
|
||||||
|
// to a successful completion, we flip the flag at the very end and don't
|
||||||
|
// display anything.
|
||||||
|
showTraefikLog := true
|
||||||
|
defer func() {
|
||||||
|
if showTraefikLog {
|
||||||
|
s.displayTraefikLog(c, output)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Create test application to be deployed.
|
||||||
|
app := marathon.NewDockerApplication().
|
||||||
|
Name("/whoami").
|
||||||
|
CPU(0.1).
|
||||||
|
Memory(32).
|
||||||
|
AddLabel(types.LabelFrontendRule, "PathPrefix:/service")
|
||||||
|
app.Container.Docker.Bridged().
|
||||||
|
Expose(80).
|
||||||
|
Container("emilevauge/whoami")
|
||||||
|
|
||||||
|
// Deploy the test application.
|
||||||
|
deploy, err := client.UpdateApplication(app, false)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
// Wait for deployment to complete.
|
||||||
|
c.Assert(client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute), checker.IsNil)
|
||||||
|
|
||||||
|
// Query application via Traefik.
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
showTraefikLog = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,54 @@
|
||||||
zk:
|
zookeeper:
|
||||||
image: bobrik/zookeeper
|
image: zookeeper:3.4.10
|
||||||
net: host
|
|
||||||
environment:
|
|
||||||
ZK_CONFIG: tickTime=2000,initLimit=10,syncLimit=5,maxClientCnxns=128,forceSync=no,clientPort=2181
|
|
||||||
ZK_ID: " 1"
|
|
||||||
|
|
||||||
master:
|
mesos-master:
|
||||||
image: mesosphere/mesos-master:0.28.1-2.0.20.ubuntu1404
|
links:
|
||||||
net: host
|
- zookeeper
|
||||||
|
image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404
|
||||||
|
# Uncomment published ports for interactive debugging.
|
||||||
|
# ports:
|
||||||
|
# - "5050:5050"
|
||||||
environment:
|
environment:
|
||||||
MESOS_ZK: zk://127.0.0.1:2181/mesos
|
- MESOS_HOSTNAME=mesos-master
|
||||||
MESOS_HOSTNAME: 127.0.0.1
|
- MESOS_CLUSTER=local
|
||||||
MESOS_IP: 127.0.0.1
|
- MESOS_REGISTRY=in_memory
|
||||||
MESOS_QUORUM: " 1"
|
- MESOS_LOG_DIR=/var/log
|
||||||
MESOS_CLUSTER: docker-compose
|
- MESOS_WORK_DIR=/var/lib/mesos
|
||||||
MESOS_WORK_DIR: /var/lib/mesos
|
- MESOS_ZK=zk://zookeeper:2181/mesos
|
||||||
|
|
||||||
slave:
|
mesos-slave:
|
||||||
image: mesosphere/mesos-slave:0.28.1-2.0.20.ubuntu1404
|
links:
|
||||||
net: host
|
- zookeeper
|
||||||
pid: host
|
- mesos-master
|
||||||
|
image: mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5
|
||||||
privileged: true
|
privileged: true
|
||||||
|
# Uncomment published ports for interactive debugging.
|
||||||
|
# ports:
|
||||||
|
# - "5051:5051"
|
||||||
environment:
|
environment:
|
||||||
MESOS_MASTER: zk://127.0.0.1:2181/mesos
|
- MESOS_HOSTNAME=mesos-slave
|
||||||
MESOS_HOSTNAME: 127.0.0.1
|
- MESOS_CONTAINERIZERS=docker,mesos
|
||||||
MESOS_IP: 127.0.0.1
|
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
|
||||||
MESOS_CONTAINERIZERS: docker,mesos
|
- MESOS_LOG_DIR=/var/log
|
||||||
volumes:
|
- MESOS_MASTER=zk://zookeeper:2181/mesos
|
||||||
- /sys/fs/cgroup:/sys/fs/cgroup
|
- MESOS_PORT=5051
|
||||||
- /usr/bin/docker:/usr/bin/docker:ro
|
- MESOS_WORK_DIR=/var/lib/mesos
|
||||||
- /usr/lib/x86_64-linux-gnu/libapparmor.so.1:/usr/lib/x86_64-linux-gnu/libapparmor.so.1:ro
|
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
|
||||||
- /lib/x86_64-linux-gnu/libsystemd-journal.so.0:/lib/x86_64-linux-gnu/libsystemd-journal.so.0
|
- MESOS_DOCKER_STOP_TIMEOUT=60secs
|
||||||
|
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
|
||||||
|
|
||||||
marathon:
|
marathon:
|
||||||
image: mesosphere/marathon:v1.1.1
|
links:
|
||||||
net: host
|
- zookeeper
|
||||||
|
- mesos-master
|
||||||
|
- mesos-slave
|
||||||
|
image: mesosphere/marathon:v1.3.12
|
||||||
|
# Uncomment published ports for interactive debugging.
|
||||||
|
# ports:
|
||||||
|
# - "8080:8080"
|
||||||
|
extra_hosts:
|
||||||
|
- "mesos-slave:172.17.0.1"
|
||||||
environment:
|
environment:
|
||||||
MARATHON_MASTER: zk://127.0.0.1:2181/mesos
|
- MARATHON_ZK=zk://zookeeper:2181/marathon
|
||||||
MARATHON_ZK: zk://127.0.0.1:2181/marathon
|
- MARATHON_MASTER=zk://zookeeper:2181/mesos
|
||||||
MARATHON_HOSTNAME: 127.0.0.1
|
|
||||||
command: --event_subscriber http_callback
|
|
||||||
|
|
Loading…
Reference in a new issue