Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Marathon integration tests. #1406

Merged
merged 2 commits into from
Aug 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ TRAEFIK_ENVS := \
-e VERSION \
-e CODENAME \
-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/')

Expand Down
4 changes: 2 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ import:
testImport:
- package: github.com/stvp/go-udp-testing
- package: github.com/docker/libcompose
version: 0ad950cbeb3d72107613dd220b5e9d7e001b890b
version: 1b708aac26a4fc6f9bff31728a8e3a252ef57dbd
- package: github.com/go-check/check
version: 11d3bc7aa68e238947792f30573146a3231fc0f1
- package: github.com/libkermit/compose
Expand Down
8 changes: 7 additions & 1 deletion integration/fixtures/marathon/simple.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
defaultEntryPoints = ["http"]

logLevel = "DEBUG"

[entryPoints]
[entryPoints.http]
address = ":8000"

logLevel = "DEBUG"
[web]
address = ":9090"

[marathon]
endpoint = "{{.MarathonURL}}"
watch = true
exposedByDefault = true
130 changes: 103 additions & 27 deletions integration/marathon_test.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,129 @@
package integration

import (
"fmt"
"net/http"
"os"
"time"

"github.com/containous/traefik/integration/try"
"github.com/containous/traefik/types"
marathon "github.com/gambol99/go-marathon"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)

const (
containerNameMesosSlave = "mesos-slave"
containerNameMarathon = "marathon"
)

// Marathon test suites (using libcompose)
type MarathonSuite struct{ BaseSuite }
type MarathonSuite struct {
BaseSuite
marathonURL string
}

func (s *MarathonSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon")
s.composeProject.Start(c)

// FIXME Doesn't work...
//// "github.com/gambol99/go-marathon"
//config := marathon.NewDefaultConfig()
//
//marathonClient, err := marathon.NewClient(config)
//if err != nil {
// c.Fatalf("Error creating Marathon client. %v", err)
//}
//
//// Wait for Marathon to elect itself leader
//err = try.Do(30*time.Second, func() error {
// leader, err := marathonClient.Leader()
//
// if err != nil || len(leader) == 0 {
// return fmt.Errorf("Leader not found. %v", err)
// }
//
// return nil
//})
//
//c.Assert(err, checker.IsNil)
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
s.marathonURL = "http://" + marathonIPAddr + ":8080"

// Wait for Marathon readiness prior to creating the client so that we
// don't run into the "all cluster members down" state right from the
// start.
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)

// Add entry for Mesos slave container IP address in the hosts file so
// that Traefik can properly forward traffic.
// This is necessary as long as we are still using the docker-compose v1
// spec. Once we switch to v2 or higher, we can have both the test/builder
// 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
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
c.Assert(err, checker.IsNil)
}

func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) {
cmd, _ := s.cmdTraefik(withConfigFile("fixtures/marathon/simple.toml"))
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
// 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()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()

// TODO validate : run on 80
// Expected a 404 as we did not configure anything
err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
// Wait for Traefik to turn ready.
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
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
}
81 changes: 46 additions & 35 deletions integration/resources/compose/marathon.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
zk:
image: bobrik/zookeeper
net: host
environment:
ZK_CONFIG: tickTime=2000,initLimit=10,syncLimit=5,maxClientCnxns=128,forceSync=no,clientPort=2181
ZK_ID: " 1"
zookeeper:
image: zookeeper:3.4.10

master:
image: mesosphere/mesos-master:0.28.1-2.0.20.ubuntu1404
net: host
mesos-master:
links:
- zookeeper
image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404
# Uncomment published ports for interactive debugging.
# ports:
# - "5050:5050"
environment:
MESOS_ZK: zk://127.0.0.1:2181/mesos
MESOS_HOSTNAME: 127.0.0.1
MESOS_IP: 127.0.0.1
MESOS_QUORUM: " 1"
MESOS_CLUSTER: docker-compose
MESOS_WORK_DIR: /var/lib/mesos
- MESOS_HOSTNAME=mesos-master
- MESOS_CLUSTER=local
- MESOS_REGISTRY=in_memory
- MESOS_LOG_DIR=/var/log
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_ZK=zk://zookeeper:2181/mesos

slave:
image: mesosphere/mesos-slave:0.28.1-2.0.20.ubuntu1404
net: host
pid: host
mesos-slave:
links:
- zookeeper
- mesos-master
image: mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5
privileged: true
# Uncomment published ports for interactive debugging.
# ports:
# - "5051:5051"
environment:
MESOS_MASTER: zk://127.0.0.1:2181/mesos
MESOS_HOSTNAME: 127.0.0.1
MESOS_IP: 127.0.0.1
MESOS_CONTAINERIZERS: docker,mesos
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup
- /usr/bin/docker:/usr/bin/docker:ro
- /usr/lib/x86_64-linux-gnu/libapparmor.so.1:/usr/lib/x86_64-linux-gnu/libapparmor.so.1:ro
- /var/run/docker.sock:/var/run/docker.sock
- /lib/x86_64-linux-gnu/libsystemd-journal.so.0:/lib/x86_64-linux-gnu/libsystemd-journal.so.0
- MESOS_HOSTNAME=mesos-slave
- MESOS_CONTAINERIZERS=docker,mesos
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
- MESOS_LOG_DIR=/var/log
- MESOS_MASTER=zk://zookeeper:2181/mesos
- MESOS_PORT=5051
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
- MESOS_DOCKER_STOP_TIMEOUT=60secs
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]

marathon:
image: mesosphere/marathon:v1.1.1
net: host
links:
- 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:
MARATHON_MASTER: zk://127.0.0.1:2181/mesos
MARATHON_ZK: zk://127.0.0.1:2181/marathon
MARATHON_HOSTNAME: 127.0.0.1
command: --event_subscriber http_callback
- MARATHON_ZK=zk://zookeeper:2181/marathon
- MARATHON_MASTER=zk://zookeeper:2181/mesos

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.