Marathon constraints filtering
This commit is contained in:
parent
7ddefcef72
commit
4b91204686
4 changed files with 65 additions and 20 deletions
|
@ -68,6 +68,16 @@ domain = "marathon.localhost"
|
||||||
#
|
#
|
||||||
# marathonLBCompatibility = true
|
# marathonLBCompatibility = true
|
||||||
|
|
||||||
|
# Enable filtering using Marathon constraints..
|
||||||
|
# If enabled, Traefik will read Marathon constraints, as defined in https://mesosphere.github.io/marathon/docs/constraints.html
|
||||||
|
# Each individual constraint will be treated as a verbatim compounded tag.
|
||||||
|
# i.e. "rack_id:CLUSTER:rack-1", with all constraint groups concatenated together using ":"
|
||||||
|
#
|
||||||
|
# Optional
|
||||||
|
# Default: false
|
||||||
|
#
|
||||||
|
# filterMarathonConstraints = true
|
||||||
|
|
||||||
# Enable Marathon basic authentication.
|
# Enable Marathon basic authentication.
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
|
|
|
@ -44,6 +44,12 @@ func label(key, value string) func(*marathon.Application) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func constraint(value string) func(*marathon.Application) {
|
||||||
|
return func(app *marathon.Application) {
|
||||||
|
app.AddConstraint(strings.Split(value, ":")...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func labelWithService(key, value string, serviceName string) func(*marathon.Application) {
|
func labelWithService(key, value string, serviceName string) func(*marathon.Application) {
|
||||||
if len(serviceName) == 0 {
|
if len(serviceName) == 0 {
|
||||||
panic("serviceName can not be empty")
|
panic("serviceName can not be empty")
|
||||||
|
|
|
@ -53,20 +53,21 @@ var servicesPropertiesRegexp = regexp.MustCompile(`^traefik\.(?P<service_name>.+
|
||||||
// Provider holds configuration of the provider.
|
// Provider holds configuration of the provider.
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
provider.BaseProvider
|
provider.BaseProvider
|
||||||
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon" export:"true"`
|
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon" export:"true"`
|
||||||
Domain string `description:"Default domain used" export:"true"`
|
Domain string `description:"Default domain used" export:"true"`
|
||||||
ExposedByDefault bool `description:"Expose Marathon apps by default" export:"true"`
|
ExposedByDefault bool `description:"Expose Marathon apps by default" export:"true"`
|
||||||
GroupsAsSubDomains bool `description:"Convert Marathon groups to subdomains" export:"true"`
|
GroupsAsSubDomains bool `description:"Convert Marathon groups to subdomains" export:"true"`
|
||||||
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header" export:"true"`
|
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header" export:"true"`
|
||||||
MarathonLBCompatibility bool `description:"Add compatibility with marathon-lb labels" export:"true"`
|
MarathonLBCompatibility bool `description:"Add compatibility with marathon-lb labels" export:"true"`
|
||||||
TLS *types.ClientTLS `description:"Enable Docker TLS support" export:"true"`
|
FilterMarathonConstraints bool `description:"Enable use of Marathon constraints in constraint filtering" export:"true"`
|
||||||
DialerTimeout flaeg.Duration `description:"Set a non-default connection timeout for Marathon" export:"true"`
|
TLS *types.ClientTLS `description:"Enable Docker TLS support" export:"true"`
|
||||||
KeepAlive flaeg.Duration `description:"Set a non-default TCP Keep Alive time in seconds" export:"true"`
|
DialerTimeout flaeg.Duration `description:"Set a non-default connection timeout for Marathon" export:"true"`
|
||||||
ForceTaskHostname bool `description:"Force to use the task's hostname." export:"true"`
|
KeepAlive flaeg.Duration `description:"Set a non-default TCP Keep Alive time in seconds" export:"true"`
|
||||||
Basic *Basic `description:"Enable basic authentication" export:"true"`
|
ForceTaskHostname bool `description:"Force to use the task's hostname." export:"true"`
|
||||||
RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments" export:"true"`
|
Basic *Basic `description:"Enable basic authentication" export:"true"`
|
||||||
readyChecker *readinessChecker
|
RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments" export:"true"`
|
||||||
marathonClient marathon.Marathon
|
readyChecker *readinessChecker
|
||||||
|
marathonClient marathon.Marathon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic holds basic authentication specific configurations
|
// Basic holds basic authentication specific configurations
|
||||||
|
@ -247,6 +248,11 @@ func (p *Provider) applicationFilter(app marathon.Application) bool {
|
||||||
constraintTags = append(constraintTags, label)
|
constraintTags = append(constraintTags, label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if p.FilterMarathonConstraints && app.Constraints != nil {
|
||||||
|
for _, constraintParts := range *app.Constraints {
|
||||||
|
constraintTags = append(constraintTags, strings.Join(constraintParts, ":"))
|
||||||
|
}
|
||||||
|
}
|
||||||
if ok, failingConstraint := p.MatchConstraints(constraintTags); !ok {
|
if ok, failingConstraint := p.MatchConstraints(constraintTags); !ok {
|
||||||
if failingConstraint != nil {
|
if failingConstraint != nil {
|
||||||
log.Debugf("Filtering Marathon application %v pruned by '%v' constraint", app.ID, failingConstraint.String())
|
log.Debugf("Filtering Marathon application %v pruned by '%v' constraint", app.ID, failingConstraint.String())
|
||||||
|
|
|
@ -519,10 +519,11 @@ func TestMarathonTaskFilter(t *testing.T) {
|
||||||
|
|
||||||
func TestMarathonApplicationFilterConstraints(t *testing.T) {
|
func TestMarathonApplicationFilterConstraints(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
desc string
|
desc string
|
||||||
application marathon.Application
|
application marathon.Application
|
||||||
marathonLBCompatibility bool
|
marathonLBCompatibility bool
|
||||||
expected bool
|
filterMarathonConstraints bool
|
||||||
|
expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "tags missing",
|
desc: "tags missing",
|
||||||
|
@ -536,6 +537,27 @@ func TestMarathonApplicationFilterConstraints(t *testing.T) {
|
||||||
marathonLBCompatibility: false,
|
marathonLBCompatibility: false,
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "constraint missing",
|
||||||
|
application: application(),
|
||||||
|
marathonLBCompatibility: false,
|
||||||
|
filterMarathonConstraints: true,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "constraint invalid",
|
||||||
|
application: application(constraint("service_cluster:CLUSTER:test")),
|
||||||
|
marathonLBCompatibility: false,
|
||||||
|
filterMarathonConstraints: true,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "constraint valid",
|
||||||
|
application: application(constraint("valid")),
|
||||||
|
marathonLBCompatibility: false,
|
||||||
|
filterMarathonConstraints: true,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "LB compatibility tag matching",
|
desc: "LB compatibility tag matching",
|
||||||
application: application(
|
application: application(
|
||||||
|
@ -552,8 +574,9 @@ func TestMarathonApplicationFilterConstraints(t *testing.T) {
|
||||||
t.Run(c.desc, func(t *testing.T) {
|
t.Run(c.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
provider := &Provider{
|
provider := &Provider{
|
||||||
ExposedByDefault: true,
|
ExposedByDefault: true,
|
||||||
MarathonLBCompatibility: c.marathonLBCompatibility,
|
MarathonLBCompatibility: c.marathonLBCompatibility,
|
||||||
|
FilterMarathonConstraints: c.filterMarathonConstraints,
|
||||||
}
|
}
|
||||||
constraint, err := types.NewConstraint("tag==valid")
|
constraint, err := types.NewConstraint("tag==valid")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue