Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In-Memory Cache for CF Resources #59

Open
wants to merge 64 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4f31f81
Add cache objects to facade.client and cf.client
santiago-ventura Aug 12, 2024
fdbce79
Add initial logic for caching resources
santiago-ventura Aug 12, 2024
5d28fbe
fix some errors in code
santiago-ventura Aug 12, 2024
860820d
Add logic in cf client for populating the cf cache
santiago-ventura Aug 12, 2024
30a47ef
GetInstance function retrieving instance from Canch
santiago-ventura Aug 13, 2024
402e470
"Add go routine for cache execution. Include use of env variable for …
santiago-ventura Aug 13, 2024
21011cb
Check for nil and ensure resourcesCache is initialized
santiago-ventura Aug 19, 2024
9df5828
changes to client.go to refresh go routine
shilparamasamyreddy Aug 19, 2024
e625b82
added channel for cache refresh
shilparamasamyreddy Aug 19, 2024
9a5bef6
remove no needed comment
santiago-ventura Aug 20, 2024
824a3bf
correct typo
santiago-ventura Aug 20, 2024
1d3c1a6
populate cache on demand based on expiry
shilparamasamyreddy Aug 21, 2024
8df71cb
Refactoring Cache objects and adding more public functions.
santiago-ventura Aug 21, 2024
f866ead
Added config package to read env variables
shilparamasamyreddy Aug 21, 2024
4ee8437
Adjusted the existing tests
shilparamasamyreddy Aug 22, 2024
9d1041c
added licence header in config
shilparamasamyreddy Aug 22, 2024
acfd78c
added logic to remove the deleted instance from cache
shilparamasamyreddy Aug 23, 2024
edc8ddb
init instance to return owner for adopt instance scenario
shilparamasamyreddy Aug 26, 2024
16e2d61
Code for update instance to cache
shilparamasamyreddy Aug 28, 2024
061f668
Added logging for testing
shilparamasamyreddy Aug 29, 2024
85e0578
Merge branch 'main' into cf-cache-resources
RalfHammer Aug 29, 2024
80b6a84
tests for resource cache
shilparamasamyreddy Sep 2, 2024
e750753
refactored the code
shilparamasamyreddy Sep 3, 2024
b50e1a6
cf/client.go changes for resource cache
shilparamasamyreddy Sep 3, 2024
e327ccd
Client tests are added for populate resource cache
shilparamasamyreddy Sep 3, 2024
4e28306
small refactoring the code
shilparamasamyreddy Sep 3, 2024
c5e2fd4
refactoring to populate resource cache function and few small changes
shilparamasamyreddy Sep 4, 2024
070ad27
update populateResourceCache
RalfHammer Sep 5, 2024
8fdff6d
improve testing of expectations
RalfHammer Sep 5, 2024
d8f0bdb
minor improvements
RalfHammer Sep 5, 2024
b03b198
improve documentation in resourcecache
RalfHammer Sep 5, 2024
554832e
minor improvements to config
RalfHammer Sep 5, 2024
f86cf76
Modified resource cache tests
shilparamasamyreddy Sep 6, 2024
6d642c8
Added caching logic for space and binding
shilparamasamyreddy Sep 10, 2024
3534115
interface to manage populate cache for all resources
shilparamasamyreddy Sep 10, 2024
03806e9
add logging for testing
shilparamasamyreddy Sep 11, 2024
cc67ad6
client and unit tests for cache
shilparamasamyreddy Sep 12, 2024
018d734
caching implementation and tests for space user role relationship
shilparamasamyreddy Sep 16, 2024
b9b7062
added todo for improvements
shilparamasamyreddy Sep 16, 2024
2cb5008
Make DeleteSpace consistent with other methods
RalfHammer Sep 18, 2024
be24a05
add config also to SpaceReconciler
RalfHammer Sep 18, 2024
12252c7
use consistent namings
RalfHammer Sep 18, 2024
277feef
remove debug log, harmonize coding
RalfHammer Sep 18, 2024
717817f
update official documentation with the new cache feature
santiago-ventura Sep 18, 2024
6a2214f
Update operator.md
santiago-ventura Sep 19, 2024
4467f58
Update based on review comments
santiago-ventura Sep 19, 2024
6c99dc4
remove error in markdown
santiago-ventura Sep 19, 2024
11a962b
simplify/document populate functions
RalfHammer Sep 19, 2024
863e518
remove not needed length check
RalfHammer Sep 19, 2024
443f26c
Add TODO for keys in shared resource cache
RalfHammer Sep 19, 2024
109a262
health.go uses the cache to retrieve the space
santiago-ventura Sep 20, 2024
5fbc0ad
small fix to mutex
shilparamasamyreddy Sep 20, 2024
a092be5
modified the global cfResourceCache logic
shilparamasamyreddy Sep 26, 2024
cb8068a
remove temporary log messages
RalfHammer Sep 26, 2024
781fb58
enable resource cache in launch.json
RalfHammer Sep 26, 2024
f1d443c
remove unneccessary type
RalfHammer Sep 27, 2024
233448e
fix typo
RalfHammer Sep 27, 2024
a770254
fix linting issue
RalfHammer Oct 2, 2024
6ce7e98
get details for credentials on demand
RalfHammer Oct 2, 2024
445aea1
add logging
RalfHammer Oct 2, 2024
1eea3f2
fix error message
RalfHammer Oct 7, 2024
bd782cf
Improve documentation about caching
RalfHammer Oct 7, 2024
327f9bb
re-activate tests during docker build
RalfHammer Oct 7, 2024
c5ec0b1
fix linter issues
RalfHammer Oct 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/caarlos0/env/v11 v11.2.2
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
Expand Down
85 changes: 73 additions & 12 deletions internal/cf/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ SPDX-License-Identifier: Apache-2.0
package cf

import (
"context"
"fmt"
"log"
"sync"

cfclient "github.com/cloudfoundry-community/go-cfclient/v3/client"
cfconfig "github.com/cloudfoundry-community/go-cfclient/v3/config"
"sigs.k8s.io/controller-runtime/pkg/metrics"

"github.com/sap/cf-service-operator/internal/config"
"github.com/sap/cf-service-operator/internal/facade"
cfmetrics "github.com/sap/cf-service-operator/pkg/metrics"
)
Expand All @@ -31,11 +34,13 @@ const (
type organizationClient struct {
organizationName string
client cfclient.Client
//resourceCache *facade.Cache
}

type spaceClient struct {
spaceGuid string
client cfclient.Client
spaceGuid string
client cfclient.Client
resourceCache *facade.ResourceCache
}

type clientIdentifier struct {
Expand All @@ -51,8 +56,10 @@ type clientCacheEntry struct {
}

var (
cacheMutex = &sync.Mutex{}
clientCache = make(map[clientIdentifier]*clientCacheEntry)
clientCacheMutex = &sync.Mutex{}
clientCache = make(map[clientIdentifier]*clientCacheEntry)
cfResourceCache *facade.ResourceCache
refreshResourceCacheMutex = &sync.Mutex{}
)

func newOrganizationClient(organizationName string, url string, username string, password string) (*organizationClient, error) {
Expand Down Expand Up @@ -83,6 +90,8 @@ func newOrganizationClient(organizationName string, url string, username string,
if err != nil {
return nil, err
}
// TODO:Populate resource cache for ORg client

return &organizationClient{organizationName: organizationName, client: *c}, nil
}

Expand Down Expand Up @@ -114,12 +123,13 @@ func newSpaceClient(spaceGuid string, url string, username string, password stri
if err != nil {
return nil, err
}

return &spaceClient{spaceGuid: spaceGuid, client: *c}, nil
}

func NewOrganizationClient(organizationName string, url string, username string, password string) (facade.OrganizationClient, error) {
cacheMutex.Lock()
defer cacheMutex.Unlock()
clientCacheMutex.Lock()
defer clientCacheMutex.Unlock()

// look up CF client in cache
identifier := clientIdentifier{url: url, username: username}
Expand Down Expand Up @@ -149,9 +159,9 @@ func NewOrganizationClient(organizationName string, url string, username string,
return client, err
}

func NewSpaceClient(spaceGuid string, url string, username string, password string) (facade.SpaceClient, error) {
cacheMutex.Lock()
defer cacheMutex.Unlock()
func NewSpaceClient(spaceGuid string, url string, username string, password string, config config.Config) (facade.SpaceClient, error) {
clientCacheMutex.Lock()
defer clientCacheMutex.Unlock()

// look up CF client in cache
identifier := clientIdentifier{url: url, username: username}
Expand All @@ -161,7 +171,7 @@ func NewSpaceClient(spaceGuid string, url string, username string, password stri
var client *spaceClient = nil
if isInCache {
// re-use CF client from cache and wrap it as spaceClient
client = &spaceClient{spaceGuid: spaceGuid, client: cacheEntry.client}
client = &spaceClient{spaceGuid: spaceGuid, client: cacheEntry.client, resourceCache: cfResourceCache}
if cacheEntry.password != password {
// password was rotated => delete client from cache and create a new one below
delete(clientCache, identifier)
Expand All @@ -178,12 +188,20 @@ func NewSpaceClient(spaceGuid string, url string, username string, password stri
}
}

if config.IsResourceCacheEnabled && client.resourceCache == nil {
client.resourceCache = facade.InitResourceCache()
client.resourceCache.SetResourceCacheEnabled(config.IsResourceCacheEnabled)
client.resourceCache.SetCacheTimeOut(config.CacheTimeOut)
client.populateResourceCache()
}

return client, err

}

func NewSpaceHealthChecker(spaceGuid string, url string, username string, password string) (facade.SpaceHealthChecker, error) {
cacheMutex.Lock()
defer cacheMutex.Unlock()
clientCacheMutex.Lock()
defer clientCacheMutex.Unlock()

// look up CF client in cache
identifier := clientIdentifier{url: url, username: username}
Expand Down Expand Up @@ -212,3 +230,46 @@ func NewSpaceHealthChecker(spaceGuid string, url string, username string, passwo

return client, err
}

func (c *spaceClient) populateResourceCache() {
// TODO: Create the space options
// TODO: Add for loop for space
refreshResourceCacheMutex.Lock()
defer refreshResourceCacheMutex.Unlock()
if c.resourceCache.IsCacheExpired() {
instanceOptions := cfclient.NewServiceInstanceListOptions()
instanceOptions.ListOptions.LabelSelector.EqualTo(labelOwner)
instanceOptions.Page = 1
instanceOptions.PerPage = 500
//instanceOptions.OrganizationGUIDs.EqualTo("21dc8fd6-ea17-49df-99e9-cacf57b479fc")

ctx := context.Background()
// populate instance cache
for {
srvInstanes, pager, err := c.client.ServiceInstances.List(ctx, instanceOptions)
if err != nil {
log.Fatalf("Error listing service instances: %s", err)
}

// Cache the service instance
for _, serviceInstance := range srvInstanes {
// ... some caching logic
instance, err := InitInstance(serviceInstance)
// instance is added to cache only if error is nil
if err == nil {
c.resourceCache.AddInstanceInCache(*serviceInstance.Metadata.Labels[labelOwner], instance)
}
}

if !pager.HasNextPage() {
fmt.Printf("No more pages\n")
break
}

pager.NextPage(instanceOptions)
}
c.resourceCache.SetLastCacheTime()
cfResourceCache = c.resourceCache
}
// TODO: Add for loop for bindings
}
24 changes: 17 additions & 7 deletions internal/cf/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
. "github.com/onsi/gomega"
"github.com/onsi/gomega/ghttp"
"github.com/prometheus/client_golang/prometheus"
"github.com/sap/cf-service-operator/internal/config"
"sigs.k8s.io/controller-runtime/pkg/metrics"
)

Expand Down Expand Up @@ -49,6 +50,15 @@ func TestCFClient(t *testing.T) {
RunSpecs(t, "CF Client Test Suite")
}

// is resource cache enabled and cache timeout
var resourceCacheEnabled = false
var resourceCacheTimeout = 5 * time.Minute

var cfg = &config.Config{
IsResourceCacheEnabled: resourceCacheEnabled,
CacheTimeOut: resourceCacheTimeout.String(),
}

// -----------------------------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -224,7 +234,7 @@ var _ = Describe("CF Client tests", Ordered, func() {
})

It("should create SpaceClient", func() {
NewSpaceClient(OrgName, url, Username, Password)
NewSpaceClient(OrgName, url, Username, Password, *cfg)

// Discover UAA endpoint
Expect(server.ReceivedRequests()[0].Method).To(Equal("GET"))
Expand All @@ -234,7 +244,7 @@ var _ = Describe("CF Client tests", Ordered, func() {
})

It("should be able to query some space", func() {
spaceClient, err := NewSpaceClient(OrgName, url, Username, Password)
spaceClient, err := NewSpaceClient(OrgName, url, Username, Password, *cfg)
Expect(err).To(BeNil())

spaceClient.GetInstance(ctx, map[string]string{"owner": Owner})
Expand Down Expand Up @@ -266,11 +276,11 @@ var _ = Describe("CF Client tests", Ordered, func() {
})

It("should be able to query some space twice", func() {
spaceClient, err := NewSpaceClient(OrgName, url, Username, Password)
spaceClient, err := NewSpaceClient(OrgName, url, Username, Password, *cfg)
Expect(err).To(BeNil())

spaceClient.GetInstance(ctx, map[string]string{"owner": Owner})
spaceClient, err = NewSpaceClient(OrgName, url, Username, Password)
spaceClient, err = NewSpaceClient(OrgName, url, Username, Password, *cfg)
Expect(err).To(BeNil())
spaceClient.GetInstance(ctx, map[string]string{"owner": Owner})

Expand All @@ -293,7 +303,7 @@ var _ = Describe("CF Client tests", Ordered, func() {

It("should be able to query two different spaces", func() {
// test space 1
spaceClient1, err1 := NewSpaceClient(SpaceName, url, Username, Password)
spaceClient1, err1 := NewSpaceClient(SpaceName, url, Username, Password, *cfg)
Expect(err1).To(BeNil())
spaceClient1.GetInstance(ctx, map[string]string{"owner": Owner})
// Discover UAA endpoint
Expand All @@ -307,7 +317,7 @@ var _ = Describe("CF Client tests", Ordered, func() {
Expect(server.ReceivedRequests()[2].RequestURI).To(ContainSubstring(Owner))

// test space 2
spaceClient2, err2 := NewSpaceClient(SpaceName2, url, Username, Password)
spaceClient2, err2 := NewSpaceClient(SpaceName2, url, Username, Password, *cfg)
Expect(err2).To(BeNil())
spaceClient2.GetInstance(ctx, map[string]string{"owner": Owner2})
// no discovery of UAA endpoint or oAuth token here due to caching
Expand Down Expand Up @@ -336,7 +346,7 @@ var _ = Describe("CF Client tests", Ordered, func() {
})

It("should register prometheus metrics for SpaceClient", func() {
spaceClient, err := NewSpaceClient(SpaceName, url, Username, Password)
spaceClient, err := NewSpaceClient(SpaceName, url, Username, Password, *cfg)
Expect(err).To(BeNil())
Expect(spaceClient).ToNot(BeNil())

Expand Down
Loading