From d74ea22d7d6345e75f4798e97e0327c1df8540d4 Mon Sep 17 00:00:00 2001 From: Diego de Oliveira Date: Fri, 6 Jan 2017 13:26:50 -0200 Subject: [PATCH] IP-per-task: (#841) Support IP per task with marathon/mesos --- glide.lock | 89 +++++++++++++-------------- glide.yaml | 8 +-- mocks/Marathon.go | 45 +++++++++++--- provider/marathon.go | 85 ++++++++++++++++++++++---- provider/marathon_test.go | 124 ++++++++++++++++++++++++++++++++++++-- templates/marathon.tmpl | 2 +- 6 files changed, 279 insertions(+), 74 deletions(-) diff --git a/glide.lock b/glide.lock index 99e89eeab..79a754d10 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 0801f9e0d663717d9cc81ee3440380d82d22a0af7dc00b078d812bd3e734c7f3 -updated: 2016-12-19T15:05:24.156719846+01:00 +hash: b45763571b0e62d44908c8c5088d9d596831f70cd3534b4ed7f8b7f62e37a38e +updated: 2016-12-29T23:00:30.216963153-02:00 imports: - name: github.com/abbot/go-http-auth version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 @@ -35,11 +35,11 @@ imports: - private/waiter - service/route53 - name: github.com/Azure/azure-sdk-for-go - version: 0984e0641ae43b89283223034574d6465be93bf4 + version: 1620af6b32398bfc91827ceae54a8cc1f55df04d subpackages: - arm/dns - name: github.com/Azure/go-autorest - version: e0c77ecbe74311e03f2a629834d2110f031f1453 + version: 32cc2321122a649b7ba4e323527bcb145134fd47 subpackages: - autorest - autorest/azure @@ -49,7 +49,7 @@ imports: - name: github.com/blang/semver version: 3a37c301dda64cbe17f16f661b4c976803c0e2d2 - name: github.com/boltdb/bolt - version: f4c032d907f61f08dba2d719c58f108a1abb8e81 + version: 5cc10bbbc5c141029940133bb33c9e969512a698 - name: github.com/BurntSushi/toml version: 99064174e013895bbd9b025c31100bd1d9b590ca - name: github.com/BurntSushi/ty @@ -63,7 +63,7 @@ imports: - name: github.com/codegangsta/cli version: bf4a526f48af7badd25d2cb02d587e1b01be3b50 - name: github.com/codegangsta/negroni - version: 3f7ce7b928e14ff890b067e5bbbc80af73690a9c + version: dc6b9d037e8dab60cbfc09c61d6932537829be8b - name: github.com/containous/flaeg version: a731c034dda967333efce5f8d276aeff11f8ff87 - name: github.com/containous/mux @@ -79,7 +79,7 @@ imports: - pkg/pathutil - pkg/types - name: github.com/coreos/go-oidc - version: dedb650fb29c39c2f21aa88c1e4cec66da8754d1 + version: 9e117111587506b9dc83b7b38263268bf48352ea subpackages: - http - jose @@ -108,7 +108,7 @@ imports: - name: github.com/dgrijalva/jwt-go version: 9ed569b5d1ac936e6494082958d63a6aa4fff99a - name: github.com/docker/distribution - version: 99cb7c0946d2f5a38015443e515dc916295064d7 + version: 87917f30529e6a7fca8eaff2932424915fb11225 subpackages: - context - digest @@ -188,7 +188,7 @@ imports: - types/time - types/versions - name: github.com/docker/go-connections - version: 988efe982fdecb46f01d53465878ff1f2ff411ce + version: 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a subpackages: - nat - sockets @@ -196,9 +196,9 @@ imports: - name: github.com/docker/go-units version: f2d77a61e3c169b43402a0a1e84f06daf29b8190 - name: github.com/docker/leadership - version: 0a913e2d71a12fd14a028452435cb71ac8d82cb6 + version: bfc7753dd48af19513b29deec23c364bf0f274eb - name: github.com/docker/libkv - version: 3fce6a0f26e07da3eac45796a8e255547a47a750 + version: 35d3e2084c650109e7bcc7282655b1bc8ba924ff subpackages: - store - store/boltdb @@ -216,26 +216,26 @@ imports: - tokens - zones - name: github.com/elazarl/go-bindata-assetfs - version: 9a6736ed45b44bf3835afeebb3034b57ed329f3e + version: 57eb5e1fc594ad4b0b1dbea7b286d299e0cb43c2 - name: github.com/emicklei/go-restful version: 892402ba11a2e2fd5e1295dd633481f27365f14d subpackages: - log - swagger - name: github.com/gambol99/go-marathon - version: a558128c87724cd7430060ef5aedf39f83937f55 + version: 9ab64d9f0259e8800911d92ebcd4d5b981917919 - name: github.com/ghodss/yaml - version: a54de18a07046d8c4b26e9327698a2ebb9285b36 + version: 04f313413ffd65ce25f2541bfd2b2ceec5c0908c - name: github.com/go-ini/ini - version: 2ba15ac2dc9cdf88c110ec2dc0ced7fa45f5678c + version: 6f66b0e091edb3c7b380f7c4f0f884274d550b67 - name: github.com/go-openapi/jsonpointer version: 8d96a2dc61536b690bd36b2e9df0b3c0b62825b2 - name: github.com/go-openapi/jsonreference version: 36d33bfe519efae5632669801b180bf1a245da3b - name: github.com/go-openapi/spec - version: f7ae86df5bc115a2744343016c789a89f065a4bd + version: 34b5ffff717ab4535aef76e3dd90818bddde571b - name: github.com/go-openapi/swag - version: 3b6d86cd965820f968760d5d419cb4add096bdd7 + version: 96d7b9ebd181a1735a1c9ac87914f2b32fbf56c9 - name: github.com/gogo/protobuf version: 909568be09de550ed094403c2bf8a261b5bb730a subpackages: @@ -248,7 +248,7 @@ imports: subpackages: - proto - name: github.com/google/go-github - version: 55263f30529cb06f5b478efc333390b791cfe3b1 + version: c8ebe3a4d7f0791a6315b7410353d4084c58805d subpackages: - github - name: github.com/google/go-querystring @@ -258,21 +258,22 @@ imports: - name: github.com/google/gofuzz version: 44d81051d367757e1c7c6a5a86423ece9afcf63c - name: github.com/gorilla/context - version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 + version: 1ea25387ff6f684839d82767c1733ff4d4d15d0a - name: github.com/hashicorp/consul - version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8 + version: fce7d75609a04eeb9d4bf41c8dc592aac18fc97d subpackages: - api - name: github.com/hashicorp/go-cleanhttp - version: ad28ea4487f05916463e2423a55166280e8254b5 + version: 875fb671b3ddc66f8e2f0acc33829c8cb989a38d - name: github.com/hashicorp/go-version version: e96d3840402619007766590ecea8dd7af1292276 - name: github.com/hashicorp/serf - version: b03bf85930b2349eb04b97c8fac437495296e3e7 + version: 6c4672d66fc6312ddde18399262943e21175d831 subpackages: - coordinate + - serf - name: github.com/JamesClonk/vultr - version: a798a2e08fafd0594d113fc6123e5c147bd66213 + version: 9ec0427d51411407c0402b093a1771cb75af9679 subpackages: - lib - name: github.com/jarcoal/httpmock @@ -288,7 +289,7 @@ imports: - name: github.com/mailgun/timetools version: fd192d755b00c968d312d23f521eb0cdc6f66bd0 - name: github.com/mailru/easyjson - version: 159cdb893c982e3d1bc6450322fedd514f9c9de3 + version: 9d6630dc8c577b56cb9687a9cf9e8578aca7298a subpackages: - buffer - jlexer @@ -324,23 +325,23 @@ imports: - name: github.com/mitchellh/mapstructure version: f3009df150dadf309fdee4a54ed65c124afad715 - name: github.com/mvdan/xurls - version: de85a6f607af2e645cce05905efd9420e43b91f1 + version: fa08908f19eca8c491d68c6bd8b4b44faea6daf8 - name: github.com/NYTimes/gziphandler version: f6438dbf4a82c56684964b03956aa727b0d7816b - name: github.com/ogier/pflag version: 45c278ab3607870051a2ea9040bb85fcb8557481 - name: github.com/opencontainers/runc - version: 02f8fa7863dd3f82909a73e2061897828460d52f + version: 1a81e9ab1f138c091fe5c86d0883f87716088527 subpackages: - libcontainer/user - name: github.com/ovh/go-ovh - version: 99a1e00db4397517d87ab82c92b9d8cb60e5940b + version: a8a4c0bc40e56322142649bda7b2b4bb15145b6e subpackages: - ovh - name: github.com/parnurzeal/gorequest - version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7 + version: 045012d33ef41ea146c1b675df9296d0dc1a212d - name: github.com/pborman/uuid - version: 3d4f2ba23642d3cfd06bd4b54cf03d99d95c0f1b + version: 5007efa264d92316c43112bc573e754bc889b7b1 - name: github.com/pmezard/go-difflib version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: @@ -356,26 +357,26 @@ imports: - name: github.com/ryanuber/go-glob version: 572520ed46dbddaed19ea3d9541bdd0494163693 - name: github.com/samuel/go-zookeeper - version: 87e1bca4477a3cc767ca71be023ced183d74e538 + version: e64db453f3512cade908163702045e0f31137843 subpackages: - zk - name: github.com/satori/go.uuid version: 879c5887cd475cd7864858769793b2ceb0d44feb - name: github.com/Sirupsen/logrus - version: 3ec0642a7fb6488f65b06f9040adc67e3990296a + version: a283a10442df8dc09befd873fab202bf8a253d6a - name: github.com/spf13/pflag version: 5644820622454e71517561946e3d94b9f9db6842 - name: github.com/streamrail/concurrent-map - version: 8bf1e9bacbf65b10c81d0f4314cf2b1ebef728b5 + version: 65a174a3a4188c0b7099acbc6cfa0c53628d3287 - name: github.com/stretchr/objx version: cbeaeb16a013161a98496fad62933b1d21786672 - name: github.com/stretchr/testify - version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506 + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: - assert - mock - name: github.com/thoas/stats - version: 152b5d051953fdb6e45f14b6826962aadc032324 + version: 79b768ff1780f4e5b0ed132e192bfeefe9f85a9c - name: github.com/timewasted/linode version: 37e84520dcf74488f67654f9c775b9752c232dc1 subpackages: @@ -387,9 +388,9 @@ imports: subpackages: - codec - name: github.com/unrolled/render - version: 526faf80cd4b305bb8134abea8d20d5ced74faa6 + version: 198ad4d8b8a4612176b804ca10555b222a086b40 - name: github.com/urfave/negroni - version: e0e50f7dc431c043cb33f91b09c3419d48b7cff5 + version: fde5e16d32adc7ad637e9cd9ad21d4ebc6192535 - name: github.com/vdemeester/docker-events version: be74d4929ec1ad118df54349fda4b0cba60f849b - name: github.com/vulcand/oxy @@ -420,7 +421,7 @@ imports: subpackages: - dnsimple - name: github.com/xenolf/lego - version: cbd5d04c891979c23c3924f198e07ce32b39d282 + version: ce8fb060cb8361a9ff8b5fb7c2347fa907b6fcac subpackages: - acme - providers/dns @@ -474,7 +475,7 @@ imports: - unix - windows - name: golang.org/x/text - version: 5c6cf4f9a2357d38515014cea8c488ed22bdab90 + version: a49bea13b776691cb1b49873e5d8df96ec74831a repo: https://github.com/golang/text.git vcs: git subpackages: @@ -507,13 +508,13 @@ imports: - compute/metadata - internal - name: gopkg.in/fsnotify.v1 - version: 944cff21b3baf3ced9a880365682152ba577d348 + version: a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb - name: gopkg.in/inf.v0 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 - name: gopkg.in/ini.v1 - version: 6e4869b434bd001f6983749881c7ead3545887d8 + version: 6f66b0e091edb3c7b380f7c4f0f884274d550b67 - name: gopkg.in/mgo.v2 - version: 22287bab4379e1fbf6002fb4eb769888f3fb224c + version: 29cc868a5ca65f401ff318143f9408d02f4799cc subpackages: - bson - name: gopkg.in/ns1/ns1-go.v2 @@ -526,7 +527,7 @@ imports: - rest/model/filter - rest/model/monitor - name: gopkg.in/square/go-jose.v1 - version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d + version: e3f973b66b91445ec816dd7411ad1b6495a5a2fc subpackages: - cipher - json @@ -665,7 +666,7 @@ testImports: - name: github.com/flynn/go-shlex version: 3f9db97f856818214da2e1057f8ad84803971cff - name: github.com/go-check/check - version: 4f90aeace3a26ad7021961c297b22c42160c7b25 + version: 11d3bc7aa68e238947792f30573146a3231fc0f1 - name: github.com/gorilla/mux version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf - name: github.com/libkermit/compose @@ -677,7 +678,7 @@ testImports: - name: github.com/libkermit/docker-check version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3 - name: github.com/vbatts/tar-split - version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721 + version: 6810cedb21b2c3d0b9bb8f9af12ff2dc7a2f14df subpackages: - archive/tar - tar/asm diff --git a/glide.yaml b/glide.yaml index f8b1a3677..89467a5ab 100644 --- a/glide.yaml +++ b/glide.yaml @@ -43,8 +43,6 @@ import: - store/etcd - store/zookeeper - package: github.com/elazarl/go-bindata-assetfs -- package: github.com/gambol99/go-marathon - version: a558128c87724cd7430060ef5aedf39f83937f55 - package: github.com/containous/mux - package: github.com/hashicorp/consul subpackages: @@ -64,7 +62,7 @@ import: subpackages: - plugin/rewrite - package: github.com/xenolf/lego - version: cbd5d04c891979c23c3924f198e07ce32b39d282 + version: ce8fb060cb8361a9ff8b5fb7c2347fa907b6fcac subpackages: - acme - package: golang.org/x/net @@ -100,6 +98,8 @@ import: version: ^1.1.0 - package: k8s.io/client-go version: ^v1.5.0 +- package: github.com/gambol99/go-marathon + version: ^0.5.1 - package: github.com/gogo/protobuf version: 0.3 - package: github.com/ArthurHlt/go-eureka-client @@ -113,4 +113,4 @@ import: - daemon - package: github.com/google/go-github - package: github.com/hashicorp/go-version -- package: github.com/mvdan/xurls \ No newline at end of file +- package: github.com/mvdan/xurls diff --git a/mocks/Marathon.go b/mocks/Marathon.go index 9f21da682..bfe9329fa 100644 --- a/mocks/Marathon.go +++ b/mocks/Marathon.go @@ -147,7 +147,7 @@ func (_m *Marathon) CreateApplication(application *marathon.Application) (*marat } // DeleteApplication provides a mock function with given fields: name -func (_m *Marathon) DeleteApplication(name string) (*marathon.DeploymentID, error) { +func (_m *Marathon) DeleteApplication(name string, force bool) (*marathon.DeploymentID, error) { ret := _m.Called(name) var r0 *marathon.DeploymentID @@ -534,7 +534,7 @@ func (_m *Marathon) CreateGroup(group *marathon.Group) error { } // DeleteGroup provides a mock function with given fields: name -func (_m *Marathon) DeleteGroup(name string) (*marathon.DeploymentID, error) { +func (_m *Marathon) DeleteGroup(name string, force bool) (*marathon.DeploymentID, error) { ret := _m.Called(name) var r0 *marathon.DeploymentID @@ -557,7 +557,7 @@ func (_m *Marathon) DeleteGroup(name string) (*marathon.DeploymentID, error) { } // UpdateGroup provides a mock function with given fields: id, group -func (_m *Marathon) UpdateGroup(id string, group *marathon.Group) (*marathon.DeploymentID, error) { +func (_m *Marathon) UpdateGroup(id string, group *marathon.Group, force bool) (*marathon.DeploymentID, error) { ret := _m.Called(id, group) var r0 *marathon.DeploymentID @@ -719,17 +719,18 @@ func (_m *Marathon) Subscriptions() (*marathon.Subscriptions, error) { } // AddEventsListener provides a mock function with given fields: channel, filter -func (_m *Marathon) AddEventsListener(channel marathon.EventsChannel, filter int) error { - ret := _m.Called(channel, filter) +func (_m *Marathon) AddEventsListener(filter int) (marathon.EventsChannel, error) { + update := make(marathon.EventsChannel, 5) + ret := _m.Called(update, filter) var r0 error if rf, ok := ret.Get(0).(func(marathon.EventsChannel, int) error); ok { - r0 = rf(channel, filter) + r0 = rf(update, filter) } else { r0 = ret.Error(0) } - return r0 + return update, r0 } // RemoveEventsListener provides a mock function with given fields: channel @@ -850,3 +851,33 @@ func (_m *Marathon) AbdicateLeader() (string, error) { return r0, r1 } + +// ApplicationBy mocks the marathon client function but does nothing +func (_m *Marathon) ApplicationBy(name string, opts *marathon.GetAppOpts) (*marathon.Application, error) { + return nil, nil +} + +// Subscribe mocks the marathon client function but does nothing +func (_m *Marathon) Subscribe(string) error { + return nil +} + +// Queue mocks the marathon client function but does nothing +func (_m *Marathon) Queue() (*marathon.Queue, error) { + return nil, nil +} + +// DeleteQueueDelay mocks the marathon client function but does nothing +func (_m *Marathon) DeleteQueueDelay(appID string) error { + return nil +} + +// GroupsBy mocks the marathon client function but does nothing +func (_m *Marathon) GroupsBy(opts *marathon.GetGroupOpts) (*marathon.Groups, error) { + return nil, nil +} + +// GroupBy mocks the marathon client function but does nothing +func (_m *Marathon) GroupBy(name string, opts *marathon.GetGroupOpts) (*marathon.Group, error) { + return nil, nil +} diff --git a/provider/marathon.go b/provider/marathon.go index 17954f83f..3e98644a5 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -83,9 +83,10 @@ func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage, return err } provider.marathonClient = client - update := make(marathon.EventsChannel, 5) + if provider.Watch { - if err := client.AddEventsListener(update, marathon.EventIDApplications); err != nil { + update, err := client.AddEventsListener(marathon.EventIDApplications) + if err != nil { log.Errorf("Failed to register for events, %s", err) return err } @@ -129,6 +130,7 @@ func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage, func (provider *Marathon) loadMarathonConfig() *types.Configuration { var MarathonFuncMap = template.FuncMap{ "getBackend": provider.getBackend, + "getBackendServer": provider.getBackendServer, "getPort": provider.getPort, "getWeight": provider.getWeight, "getDomain": provider.getDomain, @@ -188,15 +190,16 @@ func (provider *Marathon) loadMarathonConfig() *types.Configuration { } func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon.Applications, exposedByDefaultFlag bool) bool { - if len(task.Ports) == 0 { - log.Debug("Filtering marathon task without port %s", task.AppID) - return false - } application, err := getApplication(task, applications.Apps) if err != nil { log.Errorf("Unable to get marathon application from task %s", task.AppID) return false } + ports := processPorts(application, task) + if len(ports) == 0 { + log.Debug("Filtering marathon task without port %s", task.AppID) + return false + } label, _ := provider.getLabel(application, "traefik.tags") constraintTags := strings.Split(label, ",") if provider.MarathonLBCompatibility { @@ -223,10 +226,9 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon. log.Debugf("Filtering marathon task %s specifying both traefik.portIndex and traefik.port labels", task.AppID) return false } - if portIndexLabel != "" { index, err := strconv.Atoi((*application.Labels)["traefik.portIndex"]) - if err != nil || index < 0 || index > len(application.Ports)-1 { + if err != nil || index < 0 || index > len(ports)-1 { log.Debugf("Filtering marathon task %s with unexpected value for traefik.portIndex label", task.AppID) return false } @@ -239,7 +241,7 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon. } var foundPort bool - for _, exposedPort := range task.Ports { + for _, exposedPort := range ports { if port == exposedPort { foundPort = true break @@ -315,17 +317,17 @@ func (provider *Marathon) getPort(task marathon.Task, applications []marathon.Ap log.Errorf("Unable to get marathon application from task %s", task.AppID) return "" } - + ports := processPorts(application, task) if portIndexLabel, err := provider.getLabel(application, "traefik.portIndex"); err == nil { if index, err := strconv.Atoi(portIndexLabel); err == nil { - return strconv.Itoa(task.Ports[index]) + return strconv.Itoa(ports[index]) } } if portValueLabel, err := provider.getLabel(application, "traefik.port"); err == nil { return portValueLabel } - for _, port := range task.Ports { + for _, port := range ports { return strconv.Itoa(port) } return "" @@ -488,3 +490,62 @@ func (provider *Marathon) getCircuitBreakerExpression(application marathon.Appli } return "NetworkErrorRatio() > 1" } + +func processPorts(application marathon.Application, task marathon.Task) []int { + + // First using application ports + if len(application.Ports) > 0 { + return application.Ports + } + + // Using default port configuration + if task.Ports != nil && len(task.Ports) > 0 { + return task.Ports + } + + // Using port definition if available + if application.PortDefinitions != nil && len(*application.PortDefinitions) > 0 { + ports := make([]int, 0) + for _, def := range *application.PortDefinitions { + if def.Port != nil { + ports = append(ports, *def.Port) + } + } + return ports + } + // If using IP-per-task using this port definition + if application.IPAddressPerTask != nil && len(*((*application.IPAddressPerTask).Discovery).Ports) > 0 { + ports := make([]int, 0) + for _, def := range *((*application.IPAddressPerTask).Discovery).Ports { + ports = append(ports, def.Number) + } + return ports + } + + return []int{} +} + +func (provider *Marathon) getBackendServer(task marathon.Task, applications []marathon.Application) string { + application, err := getApplication(task, applications) + if err != nil { + log.Errorf("Unable to get marathon application from task %s", task.AppID) + return "" + } + if len(task.IPAddresses) == 0 { + return "" + } else if len(task.IPAddresses) == 1 { + return task.IPAddresses[0].IPAddress + } else { + ipAddressIdxStr, err := provider.getLabel(application, "traefik.ipAddressIdx") + if err != nil { + log.Errorf("Unable to get marathon IPAddress from task %s", task.AppID) + return "" + } + ipAddressIdx, err := strconv.Atoi(ipAddressIdxStr) + if err != nil { + log.Errorf("Invalid marathon IPAddress from task %s", task.AppID) + return "" + } + return task.IPAddresses[ipAddressIdx].IPAddress + } +} diff --git a/provider/marathon_test.go b/provider/marathon_test.go index bb884db52..5ed916aa5 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -80,8 +80,14 @@ func TestMarathonLoadConfig(t *testing.T) { { ID: "test", AppID: "/test", - Host: "127.0.0.1", + Host: "localhost", Ports: []int{80}, + IPAddresses: []*marathon.IPAddress{ + { + IPAddress: "127.0.0.1", + Protocol: "tcp", + }, + }, }, }, }, @@ -127,8 +133,14 @@ func TestMarathonLoadConfig(t *testing.T) { { ID: "testLoadBalancerAndCircuitBreaker.dot", AppID: "/testLoadBalancerAndCircuitBreaker.dot", - Host: "127.0.0.1", + Host: "localhost", Ports: []int{80}, + IPAddresses: []*marathon.IPAddress{ + { + IPAddress: "127.0.0.1", + Protocol: "tcp", + }, + }, }, }, }, @@ -179,8 +191,14 @@ func TestMarathonLoadConfig(t *testing.T) { { ID: "testMaxConn", AppID: "/testMaxConn", - Host: "127.0.0.1", + Host: "localhost", Ports: []int{80}, + IPAddresses: []*marathon.IPAddress{ + { + IPAddress: "127.0.0.1", + Protocol: "tcp", + }, + }, }, }, }, @@ -228,8 +246,14 @@ func TestMarathonLoadConfig(t *testing.T) { { ID: "testMaxConnOnlySpecifyAmount", AppID: "/testMaxConnOnlySpecifyAmount", - Host: "127.0.0.1", + Host: "localhost", Ports: []int{80}, + IPAddresses: []*marathon.IPAddress{ + { + IPAddress: "127.0.0.1", + Protocol: "tcp", + }, + }, }, }, }, @@ -274,8 +298,14 @@ func TestMarathonLoadConfig(t *testing.T) { { ID: "testMaxConnOnlyExtractorFunc", AppID: "/testMaxConnOnlyExtractorFunc", - Host: "127.0.0.1", + Host: "localhost", Ports: []int{80}, + IPAddresses: []*marathon.IPAddress{ + { + IPAddress: "127.0.0.1", + Protocol: "tcp", + }, + }, }, }, }, @@ -387,7 +417,89 @@ func TestMarathonTaskFilter(t *testing.T) { }, { task: marathon.Task{ - AppID: "disable", + AppID: "ipAddressOnePort", + }, + applications: &marathon.Applications{ + Apps: []marathon.Application{ + { + ID: "ipAddressOnePort", + IPAddressPerTask: &marathon.IPAddressPerTask{ + Discovery: &marathon.Discovery{ + Ports: &[]marathon.Port{ + { + Number: 8880, + Name: "p1", + }, + }, + }, + }, + Labels: &map[string]string{}, + }, + }, + }, + expected: true, + exposedByDefault: true, + }, + { + task: marathon.Task{ + AppID: "ipAddressTwoPortsUseFirst", + }, + applications: &marathon.Applications{ + Apps: []marathon.Application{ + { + ID: "ipAddressTwoPortsUseFirst", + IPAddressPerTask: &marathon.IPAddressPerTask{ + Discovery: &marathon.Discovery{ + Ports: &[]marathon.Port{ + { + Number: 8898, + Name: "p1", + }, { + Number: 9999, + Name: "p1", + }, + }, + }, + }, + Labels: &map[string]string{}, + }, + }, + }, + expected: true, + exposedByDefault: true, + }, + { + task: marathon.Task{ + AppID: "ipAddressValidTwoPorts", + }, + applications: &marathon.Applications{ + Apps: []marathon.Application{ + { + ID: "ipAddressValidTwoPorts", + IPAddressPerTask: &marathon.IPAddressPerTask{ + Discovery: &marathon.Discovery{ + Ports: &[]marathon.Port{ + { + Number: 8898, + Name: "p1", + }, { + Number: 9999, + Name: "p2", + }, + }, + }, + }, + Labels: &map[string]string{ + "traefik.portIndex": "0", + }, + }, + }, + }, + expected: true, + exposedByDefault: true, + }, + { + task: marathon.Task{ Ports: []int{80}, }, applications: &marathon.Applications{ diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index 2a617a378..0c5630016 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -1,7 +1,7 @@ {{$apps := .Applications}} [backends]{{range .Tasks}} [backends."backend{{getBackend . $apps}}".servers."server-{{.ID | replace "." "-"}}"] - url = "{{getProtocol . $apps}}://{{.Host}}:{{getPort . $apps}}" + url = "{{getProtocol . $apps}}://{{getBackendServer . $apps}}:{{getPort . $apps}}" weight = {{getWeight . $apps}} {{end}}