Skip to content

Commit

Permalink
kuma-cp: add a custom version of SnapshotCache that supports arbitrar…
Browse files Browse the repository at this point in the history
…y xDS resources (#528)

* kuma-cp: add a custom version of SnapshotCache that supports arbitrary xDS resources
* code review: replace mutable `SetVersion()` operation with an immutable `WithVersion()`
* coverage: add unit tests
  • Loading branch information
yskopets authored Jan 10, 2020
1 parent 50c0418 commit 0aaa18b
Show file tree
Hide file tree
Showing 7 changed files with 1,043 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

Changes:

* feature: add a custom version of SnapshotCache that supports arbitrary xDS resources
[#528](https://github.com/Kong/kuma/pull/528)
* feature: add proto definition for Monitoring Assignment Discovery Service (MADS)
[#525](https://github.com/Kong/kuma/pull/525)
* feature: enable Envoy Admin API by default with an option to opt out
Expand Down
13 changes: 13 additions & 0 deletions pkg/mads/cache/cache_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cache_test

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestCache(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Cache Suite")
}
79 changes: 79 additions & 0 deletions pkg/mads/cache/snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package cache

import (
"github.com/pkg/errors"

envoy_cache "github.com/envoyproxy/go-control-plane/pkg/cache"

"github.com/Kong/kuma/pkg/mads"
util_xds "github.com/Kong/kuma/pkg/util/xds"
)

// NewSnapshot creates a snapshot from response types and a version.
func NewSnapshot(version string, assignments map[string]envoy_cache.Resource) *Snapshot {
return &Snapshot{
MonitoringAssignments: envoy_cache.Resources{Version: version, Items: assignments},
}
}

// Snapshot is an internally consistent snapshot of xDS resources.
type Snapshot struct {
MonitoringAssignments envoy_cache.Resources
}

var _ util_xds.Snapshot = &Snapshot{}

// GetSupportedTypes returns a list of xDS types supported by this snapshot.
func (s *Snapshot) GetSupportedTypes() []string {
return []string{mads.MonitoringAssignmentType}
}

// Consistent check verifies that the dependent resources are exactly listed in the
// snapshot.
func (s *Snapshot) Consistent() error {
if s == nil {
return errors.New("nil snapshot")
}
return nil
}

// GetResources selects snapshot resources by type.
func (s *Snapshot) GetResources(typ string) map[string]envoy_cache.Resource {
if s == nil {
return nil
}
switch typ {
case mads.MonitoringAssignmentType:
return s.MonitoringAssignments.Items
}
return nil
}

// GetVersion returns the version for a resource type.
func (s *Snapshot) GetVersion(typ string) string {
if s == nil {
return ""
}
switch typ {
case mads.MonitoringAssignmentType:
return s.MonitoringAssignments.Version
}
return ""
}

// WithVersion creates a new snapshot with a different version for a given resource type.
func (s *Snapshot) WithVersion(typ string, version string) util_xds.Snapshot {
if s == nil {
return nil
}
if s.GetVersion(typ) == version {
return s
}
switch typ {
case mads.MonitoringAssignmentType:
return &Snapshot{
MonitoringAssignments: envoy_cache.Resources{Version: version, Items: s.MonitoringAssignments.Items},
}
}
return s
}
185 changes: 185 additions & 0 deletions pkg/mads/cache/snapshot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package cache_test

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

envoy_cache "github.com/envoyproxy/go-control-plane/pkg/cache"

. "github.com/Kong/kuma/pkg/mads/cache"

observability_proto "github.com/Kong/kuma/api/observability/v1alpha1"
)

var _ = Describe("Snapshot", func() {

expectedType := "type.googleapis.com/kuma.observability.v1alpha1.MonitoringAssignment"

Describe("GetSupportedTypes()", func() {
It("should always return ['type.googleapis.com/kuma.observability.v1alpha1.MonitoringAssignment']", func() {
// when
var snapshot *Snapshot
// then
Expect(snapshot.GetSupportedTypes()).To(Equal([]string{expectedType}))

// when
snapshot = &Snapshot{}
// then
Expect(snapshot.GetSupportedTypes()).To(Equal([]string{expectedType}))
})
})

Describe("Consistent()", func() {
It("should handle `nil`", func() {
// when
var snapshot *Snapshot
// then
Expect(snapshot.Consistent()).To(MatchError("nil snapshot"))
})

It("non-`nil` snapshot should be always consistet", func() {
// when
snapshot := NewSnapshot("v1", nil)
// then
Expect(snapshot.Consistent()).To(BeNil())

// when
snapshot = NewSnapshot("v2", map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
})
// then
Expect(snapshot.Consistent()).To(BeNil())
})
})

Describe("GetResources()", func() {
It("should handle `nil`", func() {
// when
var snapshot *Snapshot
// then
Expect(snapshot.GetResources(expectedType)).To(BeNil())
})

It("should return MonitoringAssignments", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
// when
snapshot := NewSnapshot("v1", assignments)
// then
Expect(snapshot.GetResources(expectedType)).To(Equal(assignments))
})

It("should return `nil` for unsupported resource types", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
// when
snapshot := NewSnapshot("v1", assignments)
// then
Expect(snapshot.GetResources("unsupported type")).To(BeNil())
})
})

Describe("GetVersion()", func() {
It("should handle `nil`", func() {
// when
var snapshot *Snapshot
// then
Expect(snapshot.GetVersion(expectedType)).To(Equal(""))
})

It("should return proper version for a supported resource type", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
// when
snapshot := NewSnapshot("v1", assignments)
// then
Expect(snapshot.GetVersion(expectedType)).To(Equal("v1"))
})

It("should return an empty string for unsupported resource type", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
// when
snapshot := NewSnapshot("v1", assignments)
// then
Expect(snapshot.GetVersion("unsupported type")).To(Equal(""))
})
})

Describe("WithVersion()", func() {
It("should handle `nil`", func() {
// given
var snapshot *Snapshot
// when
actual := snapshot.WithVersion(expectedType, "v1")
// then
Expect(actual).To(BeNil())
})

It("should return a new snapshot if version has changed", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
snapshot := NewSnapshot("v1", assignments)
// when
actual := snapshot.WithVersion(expectedType, "v2")
// then
Expect(actual.GetVersion(expectedType)).To(Equal("v2"))
// and
Expect(actual).To(Equal(NewSnapshot("v2", assignments)))
})

It("should return the same snapshot if version has not changed", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
snapshot := NewSnapshot("v1", assignments)
// when
actual := snapshot.WithVersion(expectedType, "v1")
// then
Expect(actual.GetVersion(expectedType)).To(Equal("v1"))
// and
Expect(actual).To(BeIdenticalTo(snapshot))
})

It("should return the same snapshot if resource type is not supported", func() {
// given
assignments := map[string]envoy_cache.Resource{
"backend": &observability_proto.MonitoringAssignment{
Name: "/meshes/default/dataplanes/backend",
},
}
snapshot := NewSnapshot("v1", assignments)
// when
actual := snapshot.WithVersion("unsupported type", "v2")
// then
Expect(actual.GetVersion(expectedType)).To(Equal("v1"))
// and
Expect(actual).To(BeIdenticalTo(snapshot))
})
})
})
5 changes: 5 additions & 0 deletions pkg/mads/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package mads

const (
MonitoringAssignmentType = "type.googleapis.com/kuma.observability.v1alpha1.MonitoringAssignment"
)
Loading

0 comments on commit 0aaa18b

Please sign in to comment.