Skip to content

Commit

Permalink
kuma-cp: include dataplane tags into ClusterLoadAssignment
Browse files Browse the repository at this point in the history
  • Loading branch information
yskopets committed Nov 12, 2019
1 parent d48f59b commit a5af7e9
Show file tree
Hide file tree
Showing 22 changed files with 430 additions and 104 deletions.
23 changes: 23 additions & 0 deletions pkg/xds/envoy/envoy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
envoy_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth"

"github.com/golang/protobuf/ptypes"
pstruct "github.com/golang/protobuf/ptypes/struct"
"github.com/golang/protobuf/ptypes/wrappers"

mesh_core "github.com/Kong/kuma/pkg/core/resources/apis/mesh"
Expand Down Expand Up @@ -55,10 +56,32 @@ func CreateStaticEndpoint(clusterName string, address string, port uint32) *v2.C
}
}

func CreateLbMetadata(tags map[string]string) *envoy_core.Metadata {
if len(tags) == 0 {
return nil
}
fields := map[string]*pstruct.Value{}
for key, value := range tags {
fields[key] = &pstruct.Value{
Kind: &pstruct.Value_StringValue{
StringValue: value,
},
}
}
return &envoy_core.Metadata{
FilterMetadata: map[string]*pstruct.Struct{
"envoy.lb": &pstruct.Struct{
Fields: fields,
},
},
}
}

func CreateClusterLoadAssignment(clusterName string, endpoints []core_xds.Endpoint) *v2.ClusterLoadAssignment {
lbEndpoints := make([]*envoy_endpoint.LbEndpoint, 0, len(endpoints))
for _, ep := range endpoints {
lbEndpoints = append(lbEndpoints, &envoy_endpoint.LbEndpoint{
Metadata: CreateLbMetadata(ep.Tags),
HostIdentifier: &envoy_endpoint.LbEndpoint_Endpoint{
Endpoint: &envoy_endpoint.Endpoint{
Address: &envoy_core.Address{
Expand Down
132 changes: 116 additions & 16 deletions pkg/xds/envoy/envoy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,63 @@ var _ = Describe("Envoy", func() {
Expect(actual).To(MatchYAML(expected))
})

Describe("CreateLbMetadata()", func() {

It("should handle `nil` map of tags", func() {
// when
metadata := envoy.CreateLbMetadata(nil)
// then
Expect(metadata).To(BeNil())
})

It("should handle empty map of tags", func() {
// when
metadata := envoy.CreateLbMetadata(map[string]string{})
// then
Expect(metadata).To(BeNil())
})

type testCase struct {
tags map[string]string
expected string
}
DescribeTable("should generate Envoy metadata",
func(given testCase) {
// when
metadata := envoy.CreateLbMetadata(given.tags)
// and
actual, err := util_proto.ToYAML(metadata)
// then
Expect(err).ToNot(HaveOccurred())
Expect(actual).To(MatchYAML(given.expected))
},
Entry("map with 1 tag", testCase{
tags: map[string]string{
"service": "redis",
},
expected: `
filterMetadata:
envoy.lb:
service: redis
`,
}),
Entry("map with multiple tags", testCase{
tags: map[string]string{
"service": "redis",
"version": "v1",
"region": "eu",
},
expected: `
filterMetadata:
envoy.lb:
service: redis
version: v1
region: eu
`,
}),
)
})

Describe("'EDS' Cluster", func() {

type testCase struct {
Expand Down Expand Up @@ -236,9 +293,30 @@ var _ = Describe("Envoy", func() {
)
})

It("should generate ClusterLoadAssignment", func() {
// given
expected := `
Describe("ClusterLoadAssignment()", func() {
type testCase struct {
cluster string
endpoints []xds.Endpoint
expected string
}
DescribeTable("should generate ClusterLoadAssignment",
func(given testCase) {
// when
resource := envoy.CreateClusterLoadAssignment(given.cluster, given.endpoints)

// then
actual, err := util_proto.ToYAML(resource)

Expect(err).ToNot(HaveOccurred())
Expect(actual).To(MatchYAML(given.expected))
},
Entry("without tags", testCase{
cluster: "127.0.0.1:8080",
endpoints: []xds.Endpoint{
{Target: "192.168.0.1", Port: 8081},
{Target: "192.168.0.2", Port: 8082},
},
expected: `
clusterName: 127.0.0.1:8080
endpoints:
- lbEndpoints:
Expand All @@ -252,19 +330,41 @@ var _ = Describe("Envoy", func() {
socketAddress:
address: 192.168.0.2
portValue: 8082
`
// when
resource := envoy.CreateClusterLoadAssignment("127.0.0.1:8080",
[]xds.Endpoint{
{Target: "192.168.0.1", Port: 8081},
{Target: "192.168.0.2", Port: 8082},
})

// then
actual, err := util_proto.ToYAML(resource)

Expect(err).ToNot(HaveOccurred())
Expect(actual).To(MatchYAML(expected))
`,
}),
Entry("with tags", testCase{
cluster: "127.0.0.1:8080",
endpoints: []xds.Endpoint{
{Target: "192.168.0.1", Port: 8081, Tags: map[string]string{"service": "backend", "region": "us"}},
{Target: "192.168.0.2", Port: 8082, Tags: map[string]string{"service": "backend", "region": "eu"}},
},
expected: `
clusterName: 127.0.0.1:8080
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 192.168.0.1
portValue: 8081
metadata:
filterMetadata:
envoy.lb:
region: us
service: backend
- endpoint:
address:
socketAddress:
address: 192.168.0.2
portValue: 8082
metadata:
filterMetadata:
envoy.lb:
region: eu
service: backend
`,
}),
)
})

Describe("'inbound' listener", func() {
Expand Down
99 changes: 70 additions & 29 deletions pkg/xds/generator/outbound_proxy_generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,8 @@ var _ = Describe("OutboundProxyGenerator", func() {
// setup
gen := &generator.OutboundProxyGenerator{}

data, err := ioutil.ReadFile(filepath.Join("testdata", "outbound-proxy", given.dataplane))
Expect(err).ToNot(HaveOccurred())

dataplane := mesh_proto.Dataplane{}
Expect(util_proto.FromYAML(data, &dataplane)).To(Succeed())
Expect(util_proto.FromYAML([]byte(given.dataplane), &dataplane)).To(Succeed())

proxy := &model.Proxy{
Id: model.ProxyId{Name: "side-car", Namespace: "default", Mesh: "default"},
Expand All @@ -64,13 +61,13 @@ var _ = Describe("OutboundProxyGenerator", func() {
},
Spec: dataplane,
},
OutboundTargets: map[string][]model.Endpoint{
OutboundTargets: model.EndpointMap{
"backend": []model.Endpoint{
{Target: "192.168.0.1", Port: 8081},
{Target: "192.168.0.1", Port: 8081, Tags: map[string]string{"service": "backend", "region": "us"}},
{Target: "192.168.0.2", Port: 8082},
},
"db": []model.Endpoint{
{Target: "192.168.0.3", Port: 5432},
{Target: "192.168.0.3", Port: 5432, Tags: map[string]string{"service": "db", "role": "master"}},
},
},
Logs: logs.NewMatchedLogs(),
Expand All @@ -94,43 +91,87 @@ var _ = Describe("OutboundProxyGenerator", func() {
},
Entry("01. transparent_proxying=false, mtls=false, outbound=0", testCase{
ctx: plainCtx,
dataplane: "dataplane.0.non-transparent.input.yaml",
dataplane: ``,
expected: "01.envoy.golden.yaml",
}),
Entry("02. transparent_proxying=true, mtls=false, outbound=0", testCase{
ctx: mtlsCtx,
dataplane: "dataplane.0.transparent.input.yaml",
expected: "02.envoy.golden.yaml",
ctx: mtlsCtx,
dataplane: `
networking:
transparentProxying:
redirectPort: 15001
`,
expected: "02.envoy.golden.yaml",
}),
Entry("03. transparent_proxying=false, mtls=false, outbound=1", testCase{
ctx: plainCtx,
dataplane: "dataplane.1.non-transparent.input.yaml",
expected: "03.envoy.golden.yaml",
ctx: plainCtx,
dataplane: `
networking:
outbound:
- interface: :18080
service: backend
`,
expected: "03.envoy.golden.yaml",
}),
Entry("04. transparent_proxying=true, mtls=false, outbound=1", testCase{
ctx: mtlsCtx,
dataplane: "dataplane.1.transparent.input.yaml",
expected: "04.envoy.golden.yaml",
ctx: mtlsCtx,
dataplane: `
networking:
outbound:
- interface: :18080
service: backend
transparentProxying:
redirectPort: 15001
`,
expected: "04.envoy.golden.yaml",
}),
Entry("05. transparent_proxying=false, mtls=true, outbound=1", testCase{
ctx: plainCtx,
dataplane: "dataplane.1.non-transparent.input.yaml",
expected: "05.envoy.golden.yaml",
ctx: plainCtx,
dataplane: `
networking:
outbound:
- interface: :18080
service: backend
`,
expected: "05.envoy.golden.yaml",
}),
Entry("06. transparent_proxying=true, mtls=true, outbound=1", testCase{
ctx: mtlsCtx,
dataplane: "dataplane.1.transparent.input.yaml",
expected: "06.envoy.golden.yaml",
ctx: mtlsCtx,
dataplane: `
networking:
outbound:
- interface: :18080
service: backend
transparentProxying:
redirectPort: 15001
`,
expected: "06.envoy.golden.yaml",
}),
Entry("07. transparent_proxying=false, mtls=false, outbound=2", testCase{
ctx: plainCtx,
dataplane: "dataplane.2.non-transparent.input.yaml",
expected: "07.envoy.golden.yaml",
ctx: plainCtx,
dataplane: `
networking:
outbound:
- interface: :18080
service: backend
- interface: :54321
service: db
`,
expected: "07.envoy.golden.yaml",
}),
Entry("08. transparent_proxying=true, mtls=true, outbound=2", testCase{
ctx: mtlsCtx,
dataplane: "dataplane.2.transparent.input.yaml",
expected: "08.envoy.golden.yaml",
ctx: mtlsCtx,
dataplane: `
networking:
outbound:
- interface: :18080
service: backend
- interface: :54321
service: db
transparentProxying:
redirectPort: 15001
`,
expected: "08.envoy.golden.yaml",
}),
)
})
Loading

0 comments on commit a5af7e9

Please sign in to comment.