2017-07-06 17:28:13 +03:00
package integration
2015-09-27 16:59:51 +03:00
import (
2017-04-10 10:28:00 +03:00
"fmt"
2015-09-27 16:59:51 +03:00
"net/http"
2017-04-10 10:28:00 +03:00
"os"
2015-09-27 16:59:51 +03:00
"time"
2019-08-03 04:58:23 +03:00
"github.com/containous/traefik/v2/integration/try"
2018-07-03 11:02:03 +03:00
"github.com/gambol99/go-marathon"
2016-04-02 13:40:21 +03:00
"github.com/go-check/check"
2015-09-27 16:59:51 +03:00
checker "github.com/vdemeester/shakers"
)
2017-04-10 10:28:00 +03:00
const (
containerNameMesosSlave = "mesos-slave"
containerNameMarathon = "marathon"
)
2016-03-27 17:27:56 +03:00
// Marathon test suites (using libcompose)
2017-04-10 10:28:00 +03:00
type MarathonSuite struct {
BaseSuite
marathonURL string
}
2016-03-27 17:27:56 +03:00
func ( s * MarathonSuite ) SetUpSuite ( c * check . C ) {
s . createComposeProject ( c , "marathon" )
2016-06-06 23:33:29 +03:00
s . composeProject . Start ( c )
2017-05-17 16:22:44 +03:00
2017-04-10 10:28:00 +03:00
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 )
2016-03-27 17:27:56 +03:00
}
2017-04-10 10:28:00 +03:00
// 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
}
2017-08-21 11:46:03 +03:00
func deployApplication ( c * check . C , client marathon . Marathon , application * marathon . Application ) {
deploy , err := client . UpdateApplication ( application , false )
c . Assert ( err , checker . IsNil )
// Wait for deployment to complete.
c . Assert ( client . WaitOnDeployment ( deploy . DeploymentID , 1 * time . Minute ) , checker . IsNil )
}
2017-04-10 10:28:00 +03:00
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 )
2017-09-13 11:34:04 +03:00
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
2015-09-27 16:59:51 +03:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2015-11-04 01:06:31 +03:00
defer cmd . Process . Kill ( )
2015-09-27 16:59:51 +03:00
2017-04-10 10:28:00 +03:00
// 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 )
// Create test application to be deployed.
app := marathon . NewDockerApplication ( ) .
Name ( "/whoami" ) .
CPU ( 0.1 ) .
Memory ( 32 ) .
2019-03-14 11:30:04 +03:00
AddLabel ( "traefik.http.Routers.rt.Rule" , "PathPrefix(`/service`)" )
2017-04-10 10:28:00 +03:00
app . Container . Docker . Bridged ( ) .
Expose ( 80 ) .
2019-01-18 17:18:04 +03:00
Container ( "containous/whoami" )
2017-04-10 10:28:00 +03:00
// Deploy the test application.
2017-08-21 11:46:03 +03:00
deployApplication ( c , client , app )
2017-05-17 16:22:44 +03:00
2017-04-10 10:28:00 +03:00
// Query application via Traefik.
err = try . GetRequest ( "http://127.0.0.1:8000/service" , 30 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
2016-03-15 20:57:56 +03:00
c . Assert ( err , checker . IsNil )
2017-08-21 11:46:03 +03:00
// Create test application with services to be deployed.
app = marathon . NewDockerApplication ( ) .
Name ( "/whoami" ) .
CPU ( 0.1 ) .
Memory ( 32 ) .
2019-03-14 11:30:04 +03:00
AddLabel ( "traefik.http.Routers.app.Rule" , "PathPrefix(`/app`)" )
2017-08-21 11:46:03 +03:00
app . Container . Docker . Bridged ( ) .
Expose ( 80 ) .
2019-01-18 17:18:04 +03:00
Container ( "containous/whoami" )
2017-08-21 11:46:03 +03:00
// Deploy the test application.
deployApplication ( c , client , app )
// Query application via Traefik.
err = try . GetRequest ( "http://127.0.0.1:8000/app" , 30 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2015-09-27 16:59:51 +03:00
}