Merge pull request #720 from guilhem/marathon-lb
Add basic compatibility with marathon-lb
This commit is contained in:
commit
3b2410d904
3 changed files with 125 additions and 37 deletions
|
@ -783,6 +783,13 @@ domain = "marathon.localhost"
|
||||||
#
|
#
|
||||||
# groupsAsSubDomains = true
|
# groupsAsSubDomains = true
|
||||||
|
|
||||||
|
# Enable compatibility with marathon-lb labels
|
||||||
|
#
|
||||||
|
# Optional
|
||||||
|
# Default: false
|
||||||
|
#
|
||||||
|
# marathonLBCompatibility = true
|
||||||
|
|
||||||
# Enable Marathon basic authentication
|
# Enable Marathon basic authentication
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
|
|
|
@ -31,6 +31,7 @@ type Marathon struct {
|
||||||
ExposedByDefault bool `description:"Expose Marathon apps by default"`
|
ExposedByDefault bool `description:"Expose Marathon apps by default"`
|
||||||
GroupsAsSubDomains bool `description:"Convert Marathon groups to subdomains"`
|
GroupsAsSubDomains bool `description:"Convert Marathon groups to subdomains"`
|
||||||
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header"`
|
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header"`
|
||||||
|
MarathonLBCompatibility bool `description:"Add compatibility with marathon-lb labels"`
|
||||||
TLS *ClientTLS `description:"Enable Docker TLS support"`
|
TLS *ClientTLS `description:"Enable Docker TLS support"`
|
||||||
Basic *MarathonBasic
|
Basic *MarathonBasic
|
||||||
marathonClient marathon.Marathon
|
marathonClient marathon.Marathon
|
||||||
|
@ -194,6 +195,11 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon.
|
||||||
}
|
}
|
||||||
label, _ := provider.getLabel(application, "traefik.tags")
|
label, _ := provider.getLabel(application, "traefik.tags")
|
||||||
constraintTags := strings.Split(label, ",")
|
constraintTags := strings.Split(label, ",")
|
||||||
|
if provider.MarathonLBCompatibility {
|
||||||
|
if label, err := provider.getLabel(application, "HAPROXY_GROUP"); err == nil {
|
||||||
|
constraintTags = append(constraintTags, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
if ok, failingConstraint := provider.MatchConstraints(constraintTags); !ok {
|
if ok, failingConstraint := provider.MatchConstraints(constraintTags); !ok {
|
||||||
if failingConstraint != nil {
|
if failingConstraint != nil {
|
||||||
log.Debugf("Application %v pruned by '%v' constraint", application.ID, failingConstraint.String())
|
log.Debugf("Application %v pruned by '%v' constraint", application.ID, failingConstraint.String())
|
||||||
|
@ -263,6 +269,11 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon.
|
||||||
func (provider *Marathon) applicationFilter(app marathon.Application, filteredTasks []marathon.Task) bool {
|
func (provider *Marathon) applicationFilter(app marathon.Application, filteredTasks []marathon.Task) bool {
|
||||||
label, _ := provider.getLabel(app, "traefik.tags")
|
label, _ := provider.getLabel(app, "traefik.tags")
|
||||||
constraintTags := strings.Split(label, ",")
|
constraintTags := strings.Split(label, ",")
|
||||||
|
if provider.MarathonLBCompatibility {
|
||||||
|
if label, err := provider.getLabel(app, "HAPROXY_GROUP"); err == nil {
|
||||||
|
constraintTags = append(constraintTags, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
if ok, failingConstraint := provider.MatchConstraints(constraintTags); !ok {
|
if ok, failingConstraint := provider.MatchConstraints(constraintTags); !ok {
|
||||||
if failingConstraint != nil {
|
if failingConstraint != nil {
|
||||||
log.Debugf("Application %v pruned by '%v' constraint", app.ID, failingConstraint.String())
|
log.Debugf("Application %v pruned by '%v' constraint", app.ID, failingConstraint.String())
|
||||||
|
@ -384,6 +395,11 @@ func (provider *Marathon) getFrontendRule(application marathon.Application) stri
|
||||||
if label, err := provider.getLabel(application, "traefik.frontend.rule"); err == nil {
|
if label, err := provider.getLabel(application, "traefik.frontend.rule"); err == nil {
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
if provider.MarathonLBCompatibility {
|
||||||
|
if label, err := provider.getLabel(application, "HAPROXY_0_VHOST"); err == nil {
|
||||||
|
return "Host:" + label
|
||||||
|
}
|
||||||
|
}
|
||||||
return "Host:" + provider.getSubDomain(application.ID) + "." + provider.Domain
|
return "Host:" + provider.getSubDomain(application.ID) + "." + provider.Domain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -687,6 +687,7 @@ func TestMarathonAppConstraints(t *testing.T) {
|
||||||
application marathon.Application
|
application marathon.Application
|
||||||
filteredTasks []marathon.Task
|
filteredTasks []marathon.Task
|
||||||
expected bool
|
expected bool
|
||||||
|
marathonLBCompatibility bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
application: marathon.Application{
|
application: marathon.Application{
|
||||||
|
@ -698,28 +699,48 @@ func TestMarathonAppConstraints(t *testing.T) {
|
||||||
AppID: "foo1",
|
AppID: "foo1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
marathonLBCompatibility: false,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
application: marathon.Application{
|
application: marathon.Application{
|
||||||
ID: "foo",
|
ID: "foo2",
|
||||||
Labels: &map[string]string{
|
Labels: &map[string]string{
|
||||||
"traefik.tags": "valid",
|
"traefik.tags": "valid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
filteredTasks: []marathon.Task{
|
filteredTasks: []marathon.Task{
|
||||||
{
|
{
|
||||||
AppID: "foo",
|
AppID: "foo2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
marathonLBCompatibility: false,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
application: marathon.Application{
|
||||||
|
ID: "foo3",
|
||||||
|
Labels: &map[string]string{
|
||||||
|
"HAPROXY_GROUP": "valid",
|
||||||
|
"traefik.tags": "notvalid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filteredTasks: []marathon.Task{
|
||||||
|
{
|
||||||
|
AppID: "foo3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
marathonLBCompatibility: true,
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := &Marathon{}
|
for _, c := range cases {
|
||||||
|
provider := &Marathon{
|
||||||
|
MarathonLBCompatibility: c.marathonLBCompatibility,
|
||||||
|
}
|
||||||
constraint, _ := types.NewConstraint("tag==valid")
|
constraint, _ := types.NewConstraint("tag==valid")
|
||||||
provider.Constraints = []types.Constraint{*constraint}
|
provider.Constraints = []types.Constraint{*constraint}
|
||||||
for _, c := range cases {
|
|
||||||
actual := provider.applicationFilter(c.application, c.filteredTasks)
|
actual := provider.applicationFilter(c.application, c.filteredTasks)
|
||||||
if actual != c.expected {
|
if actual != c.expected {
|
||||||
t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.application)
|
t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.application)
|
||||||
|
@ -732,6 +753,7 @@ func TestMarathonTaskConstraints(t *testing.T) {
|
||||||
applications []marathon.Application
|
applications []marathon.Application
|
||||||
filteredTask marathon.Task
|
filteredTask marathon.Task
|
||||||
expected bool
|
expected bool
|
||||||
|
marathonLBCompatibility bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
applications: []marathon.Application{
|
applications: []marathon.Application{
|
||||||
|
@ -749,6 +771,7 @@ func TestMarathonTaskConstraints(t *testing.T) {
|
||||||
AppID: "foo1",
|
AppID: "foo1",
|
||||||
Ports: []int{80},
|
Ports: []int{80},
|
||||||
},
|
},
|
||||||
|
marathonLBCompatibility: false,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -764,14 +787,40 @@ func TestMarathonTaskConstraints(t *testing.T) {
|
||||||
AppID: "foo2",
|
AppID: "foo2",
|
||||||
Ports: []int{80},
|
Ports: []int{80},
|
||||||
},
|
},
|
||||||
|
marathonLBCompatibility: false,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
applications: []marathon.Application{
|
||||||
|
{
|
||||||
|
ID: "foo3",
|
||||||
|
Labels: &map[string]string{
|
||||||
|
"HAPROXY_GROUP": "valid",
|
||||||
|
"traefik.tags": "notvalid",
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
ID: "foo4",
|
||||||
|
Labels: &map[string]string{
|
||||||
|
"HAPROXY_GROUP": "notvalid",
|
||||||
|
"traefik.tags": "valid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filteredTask: marathon.Task{
|
||||||
|
AppID: "foo3",
|
||||||
|
Ports: []int{80},
|
||||||
|
},
|
||||||
|
marathonLBCompatibility: true,
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := &Marathon{}
|
for _, c := range cases {
|
||||||
|
provider := &Marathon{
|
||||||
|
MarathonLBCompatibility: c.marathonLBCompatibility,
|
||||||
|
}
|
||||||
constraint, _ := types.NewConstraint("tag==valid")
|
constraint, _ := types.NewConstraint("tag==valid")
|
||||||
provider.Constraints = []types.Constraint{*constraint}
|
provider.Constraints = []types.Constraint{*constraint}
|
||||||
for _, c := range cases {
|
|
||||||
apps := new(marathon.Applications)
|
apps := new(marathon.Applications)
|
||||||
apps.Apps = c.applications
|
apps.Apps = c.applications
|
||||||
actual := provider.taskFilter(c.filteredTask, apps, true)
|
actual := provider.taskFilter(c.filteredTask, apps, true)
|
||||||
|
@ -1152,37 +1201,53 @@ func TestMarathonGetEntryPoints(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarathonGetFrontendRule(t *testing.T) {
|
func TestMarathonGetFrontendRule(t *testing.T) {
|
||||||
provider := &Marathon{
|
|
||||||
Domain: "docker.localhost",
|
|
||||||
}
|
|
||||||
|
|
||||||
applications := []struct {
|
applications := []struct {
|
||||||
application marathon.Application
|
application marathon.Application
|
||||||
expected string
|
expected string
|
||||||
|
marathonLBCompatibility bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
application: marathon.Application{
|
application: marathon.Application{
|
||||||
Labels: &map[string]string{}},
|
Labels: &map[string]string{}},
|
||||||
|
marathonLBCompatibility: true,
|
||||||
expected: "Host:.docker.localhost",
|
expected: "Host:.docker.localhost",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
application: marathon.Application{
|
application: marathon.Application{
|
||||||
ID: "test",
|
ID: "test",
|
||||||
Labels: &map[string]string{},
|
Labels: &map[string]string{
|
||||||
|
"HAPROXY_0_VHOST": "foo.bar",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
marathonLBCompatibility: false,
|
||||||
expected: "Host:test.docker.localhost",
|
expected: "Host:test.docker.localhost",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
application: marathon.Application{
|
application: marathon.Application{
|
||||||
Labels: &map[string]string{
|
Labels: &map[string]string{
|
||||||
"traefik.frontend.rule": "Host:foo.bar",
|
"traefik.frontend.rule": "Host:foo.bar",
|
||||||
|
"HAPROXY_0_VHOST": "notvalid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
marathonLBCompatibility: true,
|
||||||
|
expected: "Host:foo.bar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
application: marathon.Application{
|
||||||
|
Labels: &map[string]string{
|
||||||
|
"HAPROXY_0_VHOST": "foo.bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
marathonLBCompatibility: true,
|
||||||
expected: "Host:foo.bar",
|
expected: "Host:foo.bar",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range applications {
|
for _, a := range applications {
|
||||||
|
provider := &Marathon{
|
||||||
|
Domain: "docker.localhost",
|
||||||
|
MarathonLBCompatibility: a.marathonLBCompatibility,
|
||||||
|
}
|
||||||
actual := provider.getFrontendRule(a.application)
|
actual := provider.getFrontendRule(a.application)
|
||||||
if actual != a.expected {
|
if actual != a.expected {
|
||||||
t.Fatalf("expected %q, got %q", a.expected, actual)
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
||||||
|
|
Loading…
Reference in a new issue