Merge branch 'v2.1' into master
This commit is contained in:
commit
829649e905
73 changed files with 1497 additions and 517 deletions
|
@ -12,23 +12,23 @@ import (
|
|||
// 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
|
||||
type constraintLabelFunc func(map[string]string) bool
|
||||
|
||||
// Match reports whether the expression matches with the given labels.
|
||||
// MatchLabels 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) {
|
||||
func MatchLabels(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,
|
||||
AND: andLabelFunc,
|
||||
NOT: notLabelFunc,
|
||||
OR: orLabelFunc,
|
||||
},
|
||||
Functions: map[string]interface{}{
|
||||
"Label": labelFn,
|
||||
|
@ -45,20 +45,20 @@ func Match(labels map[string]string, expr string) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
fn, ok := parse.(constraintFunc)
|
||||
fn, ok := parse.(constraintLabelFunc)
|
||||
if !ok {
|
||||
return false, errors.New("not a constraintFunc")
|
||||
return false, errors.New("not a constraintLabelFunc")
|
||||
}
|
||||
return fn(labels), nil
|
||||
}
|
||||
|
||||
func labelFn(name, value string) constraintFunc {
|
||||
func labelFn(name, value string) constraintLabelFunc {
|
||||
return func(labels map[string]string) bool {
|
||||
return labels[name] == value
|
||||
}
|
||||
}
|
||||
|
||||
func labelRegexFn(name, expr string) constraintFunc {
|
||||
func labelRegexFn(name, expr string) constraintLabelFunc {
|
||||
return func(labels map[string]string) bool {
|
||||
matched, err := regexp.MatchString(expr, labels[name])
|
||||
if err != nil {
|
||||
|
@ -68,7 +68,7 @@ func labelRegexFn(name, expr string) constraintFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func marathonFn(value string) constraintFunc {
|
||||
func marathonFn(value string) constraintLabelFunc {
|
||||
return func(labels map[string]string) bool {
|
||||
for k, v := range labels {
|
||||
if strings.HasPrefix(k, MarathonConstraintPrefix) {
|
||||
|
@ -81,19 +81,19 @@ func marathonFn(value string) constraintFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func andFunc(a, b constraintFunc) constraintFunc {
|
||||
func andLabelFunc(a, b constraintLabelFunc) constraintLabelFunc {
|
||||
return func(labels map[string]string) bool {
|
||||
return a(labels) && b(labels)
|
||||
}
|
||||
}
|
||||
|
||||
func orFunc(a, b constraintFunc) constraintFunc {
|
||||
func orLabelFunc(a, b constraintLabelFunc) constraintLabelFunc {
|
||||
return func(labels map[string]string) bool {
|
||||
return a(labels) || b(labels)
|
||||
}
|
||||
}
|
||||
|
||||
func notFunc(a constraintFunc) constraintFunc {
|
||||
func notLabelFunc(a constraintLabelFunc) constraintLabelFunc {
|
||||
return func(labels map[string]string) bool {
|
||||
return !a(labels)
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMatch(t *testing.T) {
|
||||
func TestMatchLabels(t *testing.T) {
|
||||
testCases := []struct {
|
||||
expr string
|
||||
labels map[string]string
|
||||
|
@ -192,7 +192,7 @@ func TestMatch(t *testing.T) {
|
|||
t.Run(test.expr, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
matches, err := Match(test.labels, test.expr)
|
||||
matches, err := MatchLabels(test.labels, test.expr)
|
||||
if test.expectedErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
92
pkg/provider/constraints/constraints_tags.go
Normal file
92
pkg/provider/constraints/constraints_tags.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package constraints
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
|
||||
"github.com/vulcand/predicate"
|
||||
)
|
||||
|
||||
type constraintTagFunc func([]string) bool
|
||||
|
||||
// MatchTags reports whether the expression matches with the given tags.
|
||||
// The expression must match any logical boolean combination of:
|
||||
// - `Tag(tagValue)`
|
||||
// - `TagRegex(regexValue)`
|
||||
func MatchTags(tags []string, expr string) (bool, error) {
|
||||
if expr == "" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
p, err := predicate.NewParser(predicate.Def{
|
||||
Operators: predicate.Operators{
|
||||
AND: andTagFunc,
|
||||
NOT: notTagFunc,
|
||||
OR: orTagFunc,
|
||||
},
|
||||
Functions: map[string]interface{}{
|
||||
"Tag": tagFn,
|
||||
"TagRegex": tagRegexFn,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
parse, err := p.Parse(expr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
fn, ok := parse.(constraintTagFunc)
|
||||
if !ok {
|
||||
return false, errors.New("not a constraintTagFunc")
|
||||
}
|
||||
return fn(tags), nil
|
||||
}
|
||||
|
||||
func tagFn(name string) constraintTagFunc {
|
||||
return func(tags []string) bool {
|
||||
for _, tag := range tags {
|
||||
if tag == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func tagRegexFn(expr string) constraintTagFunc {
|
||||
return func(tags []string) bool {
|
||||
exp, err := regexp.Compile(expr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
if exp.MatchString(tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func andTagFunc(a, b constraintTagFunc) constraintTagFunc {
|
||||
return func(tags []string) bool {
|
||||
return a(tags) && b(tags)
|
||||
}
|
||||
}
|
||||
|
||||
func orTagFunc(a, b constraintTagFunc) constraintTagFunc {
|
||||
return func(tags []string) bool {
|
||||
return a(tags) || b(tags)
|
||||
}
|
||||
}
|
||||
|
||||
func notTagFunc(a constraintTagFunc) constraintTagFunc {
|
||||
return func(tags []string) bool {
|
||||
return !a(tags)
|
||||
}
|
||||
}
|
111
pkg/provider/constraints/constraints_tags_test.go
Normal file
111
pkg/provider/constraints/constraints_tags_test.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
package constraints
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMatchTags(t *testing.T) {
|
||||
testCases := []struct {
|
||||
expr string
|
||||
tags []string
|
||||
expected bool
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
expr: `Tag("world")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `Tag("worlds")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
expr: `!Tag("world")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
expr: `Tag("hello") && Tag("world")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `Tag("hello") && Tag("worlds")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
expr: `Tag("hello") && !Tag("world")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
expr: `Tag("hello") || Tag( "world")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `Tag( "worlds") || Tag("hello")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `Tag("hello") || !Tag("world")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `Tag()`,
|
||||
tags: []string{"hello", "world"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
expr: `Foo("hello")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
expr: `Tag("hello")`,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
expr: ``,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `TagRegex("hel\\w+")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
expr: `TagRegex("hell\\w+s")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
expr: `!TagRegex("hel\\w+")`,
|
||||
tags: []string{"hello", "world"},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.expr, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
matches, err := MatchTags(test.tags, test.expr)
|
||||
if test.expectedErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, test.expected, matches)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData) *dy
|
|||
configurations := make(map[string]*dynamic.Configuration)
|
||||
|
||||
for _, item := range items {
|
||||
svcName := item.Name + "-" + item.ID
|
||||
svcName := item.Node + "-" + item.Name + "-" + item.ID
|
||||
ctxSvc := log.With(ctx, log.Str("serviceName", svcName))
|
||||
|
||||
if !p.keepContainer(ctxSvc, item) {
|
||||
|
@ -80,7 +80,7 @@ func (p *Provider) keepContainer(ctx context.Context, item itemData) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
matches, err := constraints.Match(item.Labels, p.Constraints)
|
||||
matches, err := constraints.MatchTags(item.Tags, p.Constraints)
|
||||
if err != nil {
|
||||
logger.Errorf("Error matching constraints expression: %v", err)
|
||||
return false
|
||||
|
|
|
@ -2,6 +2,7 @@ package consulcatalog
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
|
@ -25,6 +26,7 @@ func TestDefaultRule(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "id",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Address: "127.0.0.1",
|
||||
Port: "80",
|
||||
|
@ -66,6 +68,7 @@ func TestDefaultRule(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "id",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Address: "127.0.0.1",
|
||||
Port: "80",
|
||||
|
@ -109,6 +112,7 @@ func TestDefaultRule(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -145,6 +149,7 @@ func TestDefaultRule(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -181,6 +186,7 @@ func TestDefaultRule(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -257,6 +263,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -297,6 +304,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -305,6 +313,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
},
|
||||
{
|
||||
ID: "Test2",
|
||||
Node: "Node1",
|
||||
Name: "Test2",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.2",
|
||||
|
@ -359,6 +368,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "1",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -367,6 +377,110 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
},
|
||||
{
|
||||
ID: "2",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.2",
|
||||
Port: "80",
|
||||
Status: api.HealthPassing,
|
||||
},
|
||||
},
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"Test": {
|
||||
Service: "Test",
|
||||
Rule: "Host(`Test.traefik.wtf`)",
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"Test": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://127.0.0.1:80",
|
||||
},
|
||||
{
|
||||
URL: "http://127.0.0.2:80",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "two containers with same service name & id no label on same node",
|
||||
items: []itemData{
|
||||
{
|
||||
ID: "1",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
Port: "80",
|
||||
Status: api.HealthPassing,
|
||||
},
|
||||
{
|
||||
ID: "1",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.2",
|
||||
Port: "80",
|
||||
Status: api.HealthPassing,
|
||||
},
|
||||
},
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"Test": {
|
||||
Service: "Test",
|
||||
Rule: "Host(`Test.traefik.wtf`)",
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"Test": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://127.0.0.2:80",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "two containers with same service name & id no label on different nodes",
|
||||
items: []itemData{
|
||||
{
|
||||
ID: "1",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
Port: "80",
|
||||
Status: api.HealthPassing,
|
||||
},
|
||||
{
|
||||
ID: "1",
|
||||
Node: "Node2",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.2",
|
||||
|
@ -1320,6 +1434,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.2",
|
||||
|
@ -1393,6 +1508,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
items: []itemData{
|
||||
{
|
||||
ID: "Test",
|
||||
Node: "Node1",
|
||||
Name: "Test",
|
||||
Labels: map[string]string{},
|
||||
Address: "127.0.0.1",
|
||||
|
@ -1426,7 +1542,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
Status: api.HealthPassing,
|
||||
},
|
||||
},
|
||||
constraints: `Label("traefik.tags", "bar")`,
|
||||
constraints: `Tag("traefik.tags=bar")`,
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
|
@ -1453,7 +1569,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
Status: api.HealthPassing,
|
||||
},
|
||||
},
|
||||
constraints: `Label("traefik.tags", "foo")`,
|
||||
constraints: `Tag("traefik.tags=foo")`,
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
|
@ -1840,6 +1956,12 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
var err error
|
||||
test.items[i].ExtraConf, err = p.getConfiguration(test.items[i])
|
||||
require.NoError(t, err)
|
||||
|
||||
var tags []string
|
||||
for k, v := range test.items[i].Labels {
|
||||
tags = append(tags, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
test.items[i].Tags = tags
|
||||
}
|
||||
|
||||
configuration := p.buildConfiguration(context.Background(), test.items)
|
||||
|
|
|
@ -24,11 +24,13 @@ var _ provider.Provider = (*Provider)(nil)
|
|||
|
||||
type itemData struct {
|
||||
ID string
|
||||
Node string
|
||||
Name string
|
||||
Address string
|
||||
Port string
|
||||
Status string
|
||||
Labels map[string]string
|
||||
Tags []string
|
||||
ExtraConf configuration
|
||||
}
|
||||
|
||||
|
@ -156,7 +158,6 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
|
|||
}
|
||||
|
||||
for _, consulService := range consulServices {
|
||||
labels := tagsToNeutralLabels(consulService.ServiceTags, p.Prefix)
|
||||
address := consulService.ServiceAddress
|
||||
if address == "" {
|
||||
address = consulService.Address
|
||||
|
@ -164,10 +165,12 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
|
|||
|
||||
item := itemData{
|
||||
ID: consulService.ServiceID,
|
||||
Node: consulService.Node,
|
||||
Name: consulService.ServiceName,
|
||||
Address: address,
|
||||
Port: strconv.Itoa(consulService.ServicePort),
|
||||
Labels: labels,
|
||||
Labels: tagsToNeutralLabels(consulService.ServiceTags, p.Prefix),
|
||||
Tags: consulService.ServiceTags,
|
||||
Status: consulService.Checks.AggregatedStatus(),
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTagsToNeutralLabels(t *testing.T) {
|
||||
func Test_tagsToNeutralLabels(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
tags []string
|
||||
|
|
|
@ -127,7 +127,7 @@ func (p *Provider) keepContainer(ctx context.Context, container dockerData) bool
|
|||
return false
|
||||
}
|
||||
|
||||
matches, err := constraints.Match(container.Labels, p.Constraints)
|
||||
matches, err := constraints.MatchLabels(container.Labels, p.Constraints)
|
||||
if err != nil {
|
||||
logger.Errorf("Error matching constraints expression: %v", err)
|
||||
return false
|
||||
|
|
|
@ -185,7 +185,7 @@ func (p *Provider) keepApplication(ctx context.Context, extraConf configuration,
|
|||
}
|
||||
|
||||
// Filter by constraints.
|
||||
matches, err := constraints.Match(labels, p.Constraints)
|
||||
matches, err := constraints.MatchLabels(labels, p.Constraints)
|
||||
if err != nil {
|
||||
logger.Errorf("Error matching constraints expression: %v", err)
|
||||
return false
|
||||
|
|
|
@ -121,7 +121,7 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
matches, err := constraints.Match(service.Labels, p.Constraints)
|
||||
matches, err := constraints.MatchLabels(service.Labels, p.Constraints)
|
||||
if err != nil {
|
||||
logger.Errorf("Error matching constraints expression: %v", err)
|
||||
return false
|
||||
|
|
|
@ -193,7 +193,7 @@ func (p *Provider) parseMetadataSourcedRancherData(ctx context.Context, stacks [
|
|||
}
|
||||
|
||||
service := rancherData{
|
||||
Name: service.Name + "/" + stack.Name,
|
||||
Name: service.Name + "_" + stack.Name,
|
||||
State: service.State,
|
||||
Labels: service.Labels,
|
||||
Port: servicePort,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue