1
0
Fork 0

New constraints management.

Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Ludovic Fernandez 2019-06-21 09:24:04 +02:00 committed by Traefiker Bot
parent e9792b446f
commit fe68e9e243
40 changed files with 658 additions and 630 deletions

View file

@ -1,27 +0,0 @@
package provider
import "github.com/containous/traefik/pkg/types"
// Constrainer Filter services by constraint, matching with Traefik tags.
type Constrainer struct {
Constraints []*types.Constraint `description:"Filter services by constraint, matching with Traefik tags." export:"true"`
}
// MatchConstraints must match with EVERY single constraint
// returns first constraint that do not match or nil.
func (c *Constrainer) MatchConstraints(tags []string) (bool, *types.Constraint) {
// if there is no tags and no constraints, filtering is disabled
if len(tags) == 0 && len(c.Constraints) == 0 {
return true, nil
}
for _, constraint := range c.Constraints {
// xor: if ok and constraint.MustMatch are equal, then no tag is currently matching with the constraint
if ok := constraint.MatchConstraintWithAtLeastOneTag(tags); ok != constraint.MustMatch {
return false, constraint
}
}
// If no constraint or every constraints matching
return true, nil
}

View file

@ -0,0 +1,100 @@
package constraints
import (
"errors"
"regexp"
"strings"
"github.com/vulcand/predicate"
)
// MarathonConstraintPrefix is the prefix for each label's key created from a Marathon application constraint.
// It is used in order to create a specific and unique pattern for these labels.
const MarathonConstraintPrefix = "Traefik-Marathon-505F9E15-BDC7-45E7-828D-C06C7BAB8091"
type constraintFunc func(map[string]string) bool
// Match reports whether the expression matches with the given labels.
// The expression must match any logical boolean combination of:
// - `Label(labelName, labelValue)`
// - `LabelRegex(labelName, regexValue)`
// - `MarathonConstraint(field:operator:value)`
func Match(labels map[string]string, expr string) (bool, error) {
if expr == "" {
return true, nil
}
p, err := predicate.NewParser(predicate.Def{
Operators: predicate.Operators{
AND: andFunc,
NOT: notFunc,
OR: orFunc,
},
Functions: map[string]interface{}{
"Label": labelFn,
"LabelRegex": labelRegexFn,
"MarathonConstraint": marathonFn,
},
})
if err != nil {
return false, err
}
parse, err := p.Parse(expr)
if err != nil {
return false, err
}
fn, ok := parse.(constraintFunc)
if !ok {
return false, errors.New("not a constraintFunc")
}
return fn(labels), nil
}
func labelFn(name, value string) constraintFunc {
return func(labels map[string]string) bool {
return labels[name] == value
}
}
func labelRegexFn(name, expr string) constraintFunc {
return func(labels map[string]string) bool {
matched, err := regexp.MatchString(expr, labels[name])
if err != nil {
return false
}
return matched
}
}
func marathonFn(value string) constraintFunc {
return func(labels map[string]string) bool {
for k, v := range labels {
if strings.HasPrefix(k, MarathonConstraintPrefix) {
if v == value {
return true
}
}
}
return false
}
}
func andFunc(a, b constraintFunc) constraintFunc {
return func(labels map[string]string) bool {
return a(labels) && b(labels)
}
}
func orFunc(a, b constraintFunc) constraintFunc {
return func(labels map[string]string) bool {
return a(labels) || b(labels)
}
}
func notFunc(a constraintFunc) constraintFunc {
return func(labels map[string]string) bool {
return !a(labels)
}
}

View file

@ -0,0 +1,204 @@
package constraints
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMatch(t *testing.T) {
testCases := []struct {
expr string
labels map[string]string
expected bool
expectedErr bool
}{
{
expr: `Label("hello", "world")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: true,
},
{
expr: `Label("hello", "worlds")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `Label("hi", "world")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `!Label("hello", "world")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `Label("hello", "world") && Label("foo", "bar")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: true,
},
{
expr: `Label("hello", "worlds") && Label("foo", "bar")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `Label("hello", "world") && !Label("foo", "bar")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `Label("hello", "world") || Label("foo", "bar")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: true,
},
{
expr: `Label("hello", "worlds") || Label("foo", "bar")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: true,
},
{
expr: `Label("hello", "world") || !Label("foo", "bar")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: true,
},
{
expr: `Label("hello")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expectedErr: true,
},
{
expr: `Foo("hello")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expectedErr: true,
},
{
expr: `Label("hello", "bar")`,
expected: false,
},
{
expr: ``,
expected: true,
},
{
expr: `MarathonConstraint("bar")`,
labels: map[string]string{
"hello": "world",
MarathonConstraintPrefix + "-1": "bar",
MarathonConstraintPrefix + "-2": "foo",
},
expected: true,
},
{
expr: `MarathonConstraint("bur")`,
labels: map[string]string{
"hello": "world",
MarathonConstraintPrefix + "-1": "bar",
MarathonConstraintPrefix + "-2": "foo",
},
expected: false,
},
{
expr: `Label("hello", "world") && MarathonConstraint("bar")`,
labels: map[string]string{
"hello": "world",
MarathonConstraintPrefix + "-1": "bar",
MarathonConstraintPrefix + "-2": "foo",
},
expected: true,
},
{
expr: `LabelRegex("hello", "w\\w+")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: true,
},
{
expr: `LabelRegex("hello", "w\\w+s")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `LabelRegex("hi", "w\\w+")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `!LabelRegex("hello", "w\\w+")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
{
expr: `LabelRegex("hello", "w(\\w+")`,
labels: map[string]string{
"hello": "world",
"foo": "bar",
},
expected: false,
},
}
for _, test := range testCases {
test := test
t.Run(test.expr, func(t *testing.T) {
t.Parallel()
matches, err := Match(test.labels, test.expr)
if test.expectedErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
assert.Equal(t, test.expected, matches)
})
}
}

View file

@ -11,6 +11,7 @@ import (
"github.com/containous/traefik/pkg/config/label"
"github.com/containous/traefik/pkg/log"
"github.com/containous/traefik/pkg/provider"
"github.com/containous/traefik/pkg/provider/constraints"
"github.com/docker/go-connections/nat"
)
@ -123,10 +124,13 @@ func (p *Provider) keepContainer(ctx context.Context, container dockerData) bool
return false
}
if ok, failingConstraint := p.MatchConstraints(container.ExtraConf.Tags); !ok {
if failingConstraint != nil {
logger.Debugf("Container pruned by %q constraint", failingConstraint.String())
}
matches, err := constraints.Match(container.Labels, p.Constraints)
if err != nil {
logger.Error("Error matching constraints expression: %v", err)
return false
}
if !matches {
logger.Debugf("Container pruned by constraint expression: %q", p.Constraints)
return false
}

View file

@ -6,7 +6,6 @@ import (
"testing"
"github.com/containous/traefik/pkg/config"
"github.com/containous/traefik/pkg/types"
docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/go-connections/nat"
@ -339,7 +338,7 @@ func Test_buildConfiguration(t *testing.T) {
testCases := []struct {
desc string
containers []dockerData
constraints []*types.Constraint
constraints string
expected *config.Configuration
}{
{
@ -1924,13 +1923,7 @@ func Test_buildConfiguration(t *testing.T) {
},
},
},
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "bar",
},
},
constraints: `Label("traefik.tags", "bar")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},
@ -1965,13 +1958,7 @@ func Test_buildConfiguration(t *testing.T) {
},
},
},
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "foo",
},
},
constraints: `Label("traefik.tags", "foo")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},

View file

@ -45,7 +45,7 @@ var _ provider.Provider = (*Provider)(nil)
// Provider holds configurations of the provider.
type Provider struct {
provider.Constrainer `description:"List of constraints used to filter out some containers." export:"true"`
Constraints string `description:"Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container." export:"true"`
Watch bool `description:"Watch provider." export:"true"`
Endpoint string `description:"Docker server endpoint. Can be a tcp or a unix socket endpoint."`
DefaultRule string `description:"Default rule."`

View file

@ -14,7 +14,6 @@ const (
// configuration Contains information from the labels that are globals (not related to the dynamic configuration) or specific to the provider.
type configuration struct {
Enable bool
Tags []string
Docker specificConfiguration
}
@ -31,7 +30,7 @@ func (p *Provider) getConfiguration(container dockerData) (configuration, error)
},
}
err := label.Decode(container.Labels, &conf, "traefik.docker.", "traefik.enable", "traefik.tags")
err := label.Decode(container.Labels, &conf, "traefik.docker.", "traefik.enable")
if err != nil {
return configuration{}, err
}

View file

@ -13,6 +13,7 @@ import (
"github.com/containous/traefik/pkg/config/label"
"github.com/containous/traefik/pkg/log"
"github.com/containous/traefik/pkg/provider"
"github.com/containous/traefik/pkg/provider/constraints"
"github.com/gambol99/go-marathon"
)
@ -29,11 +30,20 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho
continue
}
if !p.keepApplication(ctxApp, extraConf) {
labels := stringValueMap(app.Labels)
if app.Constraints != nil {
for i, constraintParts := range *app.Constraints {
key := constraints.MarathonConstraintPrefix + "-" + strconv.Itoa(i)
labels[key] = strings.Join(constraintParts, ":")
}
}
if !p.keepApplication(ctxApp, extraConf, labels) {
continue
}
confFromLabel, err := label.DecodeConfiguration(stringValueMap(app.Labels))
confFromLabel, err := label.DecodeConfiguration(labels)
if err != nil {
logger.Error(err)
continue
@ -65,7 +75,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho
Labels map[string]string
}{
Name: app.ID,
Labels: stringValueMap(app.Labels),
Labels: labels,
}
serviceName := getServiceName(app)
@ -164,7 +174,7 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app maratho
return nil
}
func (p *Provider) keepApplication(ctx context.Context, extraConf configuration) bool {
func (p *Provider) keepApplication(ctx context.Context, extraConf configuration, labels map[string]string) bool {
logger := log.FromContext(ctx)
// Filter disabled application.
@ -174,10 +184,13 @@ func (p *Provider) keepApplication(ctx context.Context, extraConf configuration)
}
// Filter by constraints.
if ok, failingConstraint := p.MatchConstraints(extraConf.Tags); !ok {
if failingConstraint != nil {
logger.Debugf("Filtering Marathon application, pruned by %q constraint", failingConstraint.String())
}
matches, err := constraints.Match(labels, p.Constraints)
if err != nil {
logger.Error("Error matching constraints expression: %v", err)
return false
}
if !matches {
logger.Debugf("Marathon application filtered by constraint expression: %q", p.Constraints)
return false
}

View file

@ -6,7 +6,6 @@ import (
"testing"
"github.com/containous/traefik/pkg/config"
"github.com/containous/traefik/pkg/types"
"github.com/gambol99/go-marathon"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -29,12 +28,11 @@ func TestGetConfigurationAPIErrors(t *testing.T) {
func TestBuildConfiguration(t *testing.T) {
testCases := []struct {
desc string
applications *marathon.Applications
constraints []*types.Constraint
filterMarathonConstraints bool
defaultRule string
expected *config.Configuration
desc string
applications *marathon.Applications
constraints string
defaultRule string
expected *config.Configuration
}{
{
desc: "simple application",
@ -1065,13 +1063,7 @@ func TestBuildConfiguration(t *testing.T) {
withTasks(localhostTask(taskPorts(80, 81))),
withLabel("traefik.tags", "foo"),
)),
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "bar",
},
},
constraints: `Label("traefik.tags", "bar")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},
@ -1093,14 +1085,7 @@ func TestBuildConfiguration(t *testing.T) {
withTasks(localhostTask(taskPorts(80, 81))),
constraint("rack_id:CLUSTER:rack-1"),
)),
filterMarathonConstraints: true,
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "rack_id:CLUSTER:rack-2",
},
},
constraints: `MarathonConstraint("rack_id:CLUSTER:rack-2")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},
@ -1122,14 +1107,7 @@ func TestBuildConfiguration(t *testing.T) {
withTasks(localhostTask(taskPorts(80, 81))),
constraint("rack_id:CLUSTER:rack-1"),
)),
filterMarathonConstraints: true,
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "rack_id:CLUSTER:rack-1",
},
},
constraints: `MarathonConstraint("rack_id:CLUSTER:rack-1")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},
@ -1167,14 +1145,7 @@ func TestBuildConfiguration(t *testing.T) {
withTasks(localhostTask(taskPorts(80, 81))),
withLabel("traefik.tags", "bar"),
)),
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "bar",
},
},
constraints: `Label("traefik.tags", "bar")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},
@ -1417,9 +1388,8 @@ func TestBuildConfiguration(t *testing.T) {
}
p := &Provider{
DefaultRule: defaultRule,
ExposedByDefault: true,
FilterMarathonConstraints: test.filterMarathonConstraints,
DefaultRule: defaultRule,
ExposedByDefault: true,
}
p.Constraints = test.constraints
@ -1473,7 +1443,7 @@ func TestApplicationFilterEnabled(t *testing.T) {
extraConf, err := provider.getConfiguration(app)
require.NoError(t, err)
if provider.keepApplication(context.Background(), extraConf) != test.expected {
if provider.keepApplication(context.Background(), extraConf, stringValueMap(app.Labels)) != test.expected {
t.Errorf("got unexpected filtering = %t", !test.expected)
}
})

View file

@ -2,7 +2,6 @@ package marathon
import (
"math"
"strings"
"github.com/containous/traefik/pkg/config/label"
"github.com/gambol99/go-marathon"
@ -10,7 +9,6 @@ import (
type configuration struct {
Enable bool
Tags []string
Marathon specificConfiguration
}
@ -23,23 +21,16 @@ func (p *Provider) getConfiguration(app marathon.Application) (configuration, er
conf := configuration{
Enable: p.ExposedByDefault,
Tags: nil,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
}
err := label.Decode(labels, &conf, "traefik.marathon.", "traefik.enable", "traefik.tags")
err := label.Decode(labels, &conf, "traefik.marathon.", "traefik.enable")
if err != nil {
return configuration{}, err
}
if p.FilterMarathonConstraints && app.Constraints != nil {
for _, constraintParts := range *app.Constraints {
conf.Tags = append(conf.Tags, strings.Join(constraintParts, ":"))
}
}
return conf, nil
}

View file

@ -23,12 +23,10 @@ func TestGetConfiguration(t *testing.T) {
Labels: &map[string]string{},
},
p: Provider{
ExposedByDefault: false,
FilterMarathonConstraints: false,
ExposedByDefault: false,
},
expected: configuration{
Enable: false,
Tags: nil,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
@ -43,12 +41,10 @@ func TestGetConfiguration(t *testing.T) {
},
},
p: Provider{
ExposedByDefault: false,
FilterMarathonConstraints: false,
ExposedByDefault: false,
},
expected: configuration{
Enable: true,
Tags: nil,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
@ -63,12 +59,10 @@ func TestGetConfiguration(t *testing.T) {
},
},
p: Provider{
ExposedByDefault: false,
FilterMarathonConstraints: false,
ExposedByDefault: false,
},
expected: configuration{
Enable: false,
Tags: nil,
Marathon: specificConfiguration{
IPAddressIdx: 4,
},
@ -83,14 +77,10 @@ func TestGetConfiguration(t *testing.T) {
Labels: &map[string]string{},
},
p: Provider{
ExposedByDefault: false,
FilterMarathonConstraints: true,
ExposedByDefault: false,
},
expected: configuration{
Enable: false,
Tags: []string{
"key:value",
},
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
@ -103,12 +93,10 @@ func TestGetConfiguration(t *testing.T) {
Labels: &map[string]string{},
},
p: Provider{
ExposedByDefault: true,
FilterMarathonConstraints: false,
ExposedByDefault: true,
},
expected: configuration{
Enable: true,
Tags: nil,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
@ -123,32 +111,10 @@ func TestGetConfiguration(t *testing.T) {
},
},
p: Provider{
ExposedByDefault: true,
FilterMarathonConstraints: false,
ExposedByDefault: true,
},
expected: configuration{
Enable: false,
Tags: nil,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
},
},
{
desc: "Tags in label",
app: marathon.Application{
Constraints: &[][]string{},
Labels: &map[string]string{
"traefik.tags": "mytags",
},
},
p: Provider{
ExposedByDefault: true,
FilterMarathonConstraints: false,
},
expected: configuration{
Enable: true,
Tags: []string{"mytags"},
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},

View file

@ -45,26 +45,24 @@ var _ provider.Provider = (*Provider)(nil)
// Provider holds configuration of the provider.
type Provider struct {
provider.Constrainer `description:"List of constraints used to filter out some containers." export:"true"`
Trace bool `description:"Display additional provider logs." export:"true"`
Watch bool `description:"Watch provider." export:"true"`
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon." export:"true"`
DefaultRule string `description:"Default rule."`
ExposedByDefault bool `description:"Expose Marathon apps by default." export:"true"`
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." export:"true"`
FilterMarathonConstraints bool `description:"Enable use of Marathon constraints in constraint filtering." export:"true"`
TLS *types.ClientTLS `description:"Enable TLS support." export:"true"`
DialerTimeout types.Duration `description:"Set a dialer timeout for Marathon." export:"true"`
ResponseHeaderTimeout types.Duration `description:"Set a response header timeout for Marathon." export:"true"`
TLSHandshakeTimeout types.Duration `description:"Set a TLS handshake timeout for Marathon." export:"true"`
KeepAlive types.Duration `description:"Set a TCP Keep Alive time." export:"true"`
ForceTaskHostname bool `description:"Force to use the task's hostname." export:"true"`
Basic *Basic `description:"Enable basic authentication." export:"true"`
RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments." export:"true"`
readyChecker *readinessChecker
marathonClient marathon.Marathon
defaultRuleTpl *template.Template
Constraints string `description:"Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application." export:"true"`
Trace bool `description:"Display additional provider logs." export:"true"`
Watch bool `description:"Watch provider." export:"true"`
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon." export:"true"`
DefaultRule string `description:"Default rule."`
ExposedByDefault bool `description:"Expose Marathon apps by default." export:"true"`
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." export:"true"`
TLS *types.ClientTLS `description:"Enable TLS support." export:"true"`
DialerTimeout types.Duration `description:"Set a dialer timeout for Marathon." export:"true"`
ResponseHeaderTimeout types.Duration `description:"Set a response header timeout for Marathon." export:"true"`
TLSHandshakeTimeout types.Duration `description:"Set a TLS handshake timeout for Marathon." export:"true"`
KeepAlive types.Duration `description:"Set a TCP Keep Alive time." export:"true"`
ForceTaskHostname bool `description:"Force to use the task's hostname." export:"true"`
Basic *Basic `description:"Enable basic authentication." export:"true"`
RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments." export:"true"`
readyChecker *readinessChecker
marathonClient marathon.Marathon
defaultRuleTpl *template.Template
}
// SetDefaults sets the default values.

View file

@ -11,6 +11,7 @@ import (
"github.com/containous/traefik/pkg/config/label"
"github.com/containous/traefik/pkg/log"
"github.com/containous/traefik/pkg/provider"
"github.com/containous/traefik/pkg/provider/constraints"
)
func (p *Provider) buildConfiguration(ctx context.Context, services []rancherData) *config.Configuration {
@ -120,10 +121,13 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
return false
}
if ok, failingConstraint := p.MatchConstraints(service.ExtraConf.Tags); !ok {
if failingConstraint != nil {
logger.Debugf("service pruned by %q constraint", failingConstraint.String())
}
matches, err := constraints.Match(service.Labels, p.Constraints)
if err != nil {
logger.Error("Error matching constraints expression: %v", err)
return false
}
if !matches {
logger.Debugf("Service pruned by constraint expression: %q", p.Constraints)
return false
}

View file

@ -5,7 +5,6 @@ import (
"testing"
"github.com/containous/traefik/pkg/config"
"github.com/containous/traefik/pkg/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -14,7 +13,7 @@ func Test_buildConfiguration(t *testing.T) {
testCases := []struct {
desc string
containers []rancherData
constraints []*types.Constraint
constraints string
expected *config.Configuration
}{
{
@ -330,13 +329,7 @@ func Test_buildConfiguration(t *testing.T) {
State: "",
},
},
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "bar",
},
},
constraints: `Label("traefik.tags", "bar")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},
@ -363,13 +356,7 @@ func Test_buildConfiguration(t *testing.T) {
State: "",
},
},
constraints: []*types.Constraint{
{
Key: "tag",
MustMatch: true,
Value: "foo",
},
},
constraints: `Label("traefik.tags", "foo")`,
expected: &config.Configuration{
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{},

View file

@ -6,7 +6,6 @@ import (
type configuration struct {
Enable bool
Tags []string
}
func (p *Provider) getConfiguration(service rancherData) (configuration, error) {
@ -14,7 +13,7 @@ func (p *Provider) getConfiguration(service rancherData) (configuration, error)
Enable: p.ExposedByDefault,
}
err := label.Decode(service.Labels, &conf, "traefik.rancher.", "traefik.enable", "traefik.tags")
err := label.Decode(service.Labels, &conf, "traefik.rancher.", "traefik.enable")
if err != nil {
return configuration{}, err
}

View file

@ -40,8 +40,7 @@ var _ provider.Provider = (*Provider)(nil)
// Provider holds configurations of the provider.
type Provider struct {
provider.Constrainer `description:"List of constraints used to filter out some containers." export:"true"`
Constraints string `description:"Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container." export:"true"`
Watch bool `description:"Watch provider." export:"true"`
DefaultRule string `description:"Default rule."`
ExposedByDefault bool `description:"Expose containers by default." export:"true"`

View file

@ -25,7 +25,6 @@ type Provider struct {
// SetDefaults sets the default values.
func (p *Provider) SetDefaults() {
p.EntryPoint = "traefik"
// FIXME p.EntryPoint = static.DefaultInternalEntryPointName
}
var templatesRenderer = render.New(render.Options{Directory: "nowhere"})