Skip to content

Commit 6a684f6

Browse files
committed
Make client cache TTL configurable using configMap
1 parent 6fb8680 commit 6a684f6

File tree

6 files changed

+46
-12
lines changed

6 files changed

+46
-12
lines changed

config/rbac/role.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ metadata:
66
creationTimestamp: null
77
name: manager-role
88
rules:
9+
- apiGroups:
10+
- ""
11+
resources:
12+
- configmaps
13+
verbs:
14+
- get
15+
- list
16+
- watch
917
- apiGroups:
1018
- ""
1119
resources:

controllers/cloudstackcluster_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
// RBAC permissions used in all reconcilers. Events and Secrets.
4040
// "" empty string as the api group indicates core kubernetes objects. "*" indicates all objects.
4141
// +kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch
42+
// +kubebuilder:rbac:groups="",resources=configmaps;,verbs=get;list;watch
4243
// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
4344

4445
// RBAC permissions for CloudStackCluster.

controllers/utils/failuredomains.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,12 @@ func (c *CloudClientImplementation) AsFailureDomainUser(fdSpec *infrav1.CloudSta
111111
return ctrl.Result{}, errors.Wrapf(err, "getting ACSEndpoint secret with ref: %v", fdSpec.ACSEndpoint)
112112
}
113113

114+
clientConfig := &corev1.ConfigMap{}
115+
key = client.ObjectKey{Name: cloud.ClientConfigMapName, Namespace: cloud.ClientConfigMapNamespace}
116+
_ = c.K8sClient.Get(c.RequestCtx, key, clientConfig)
117+
114118
var err error
115-
if c.CSClient, err = cloud.NewClientFromK8sSecret(endpointCredentials); err != nil {
119+
if c.CSClient, err = cloud.NewClientFromK8sSecret(endpointCredentials, clientConfig); err != nil {
116120
return ctrl.Result{}, errors.Wrapf(err, "parsing ACSEndpoint secret with ref: %v", fdSpec.ACSEndpoint)
117121
}
118122

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module sigs.k8s.io/cluster-api-provider-cloudstack
33
go 1.16
44

55
require (
6+
github.com/ReneKroon/ttlcache v1.7.0 // indirect
67
github.com/apache/cloudstack-go/v2 v2.13.0
78
github.com/go-logr/logr v1.2.3
89
github.com/golang/mock v1.6.0

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo
7070
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
7171
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
7272
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
73+
github.com/ReneKroon/ttlcache v1.7.0 h1:8BkjFfrzVFXyrqnMtezAaJ6AHPSsVV10m6w28N/Fgkk=
74+
github.com/ReneKroon/ttlcache v1.7.0/go.mod h1:8BGGzdumrIjWxdRx8zpK6L3oGMWvIXdvB2GD1cfvd+I=
7375
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
7476
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
7577
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -600,6 +602,7 @@ go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0H
600602
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
601603
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
602604
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
605+
go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI=
603606
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
604607
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
605608
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=

pkg/cloud/client.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ type SecretConfig struct {
7373
var clientCache *ttlcache.Cache
7474
var cacheMutex sync.Mutex
7575

76-
const cacheExpiration = time.Duration(1 * time.Hour)
76+
const ClientConfigMapName = "capc-client-config"
77+
const ClientConfigMapNamespace = "capc-system"
78+
const ClientCacheTTLKey = "client-cache-ttl"
79+
const DefaultClientCacheTTL = time.Duration(1 * time.Hour)
7780

7881
// UnmarshalAllSecretConfigs parses a yaml document for each secret.
7982
func UnmarshalAllSecretConfigs(in []byte, out *[]SecretConfig) error {
@@ -94,7 +97,7 @@ func UnmarshalAllSecretConfigs(in []byte, out *[]SecretConfig) error {
9497
}
9598

9699
// NewClientFromK8sSecret returns a client from a k8s secret
97-
func NewClientFromK8sSecret(endpointSecret *corev1.Secret) (Client, error) {
100+
func NewClientFromK8sSecret(endpointSecret *corev1.Secret, clientConfig *corev1.ConfigMap) (Client, error) {
98101
endpointSecretStrings := map[string]string{}
99102
for k, v := range endpointSecret.Data {
100103
endpointSecretStrings[k] = string(v)
@@ -103,19 +106,19 @@ func NewClientFromK8sSecret(endpointSecret *corev1.Secret) (Client, error) {
103106
if err != nil {
104107
return nil, err
105108
}
106-
return NewClientFromBytesConfig(bytes)
109+
return NewClientFromBytesConfig(bytes, clientConfig)
107110
}
108111

109112
// NewClientFromBytesConfig returns a client from a bytes array that unmarshals to a yaml config.
110-
func NewClientFromBytesConfig(conf []byte) (Client, error) {
113+
func NewClientFromBytesConfig(conf []byte, clientConfig *corev1.ConfigMap) (Client, error) {
111114
r := bytes.NewReader(conf)
112115
dec := yaml.NewDecoder(r)
113116
var config Config
114117
if err := dec.Decode(&config); err != nil {
115118
return nil, err
116119
}
117120

118-
return NewClientFromConf(config)
121+
return NewClientFromConf(config, clientConfig)
119122
}
120123

121124
// NewClientFromYamlPath returns a client from a yaml config at path.
@@ -139,18 +142,16 @@ func NewClientFromYamlPath(confPath string, secretName string) (Client, error) {
139142
return nil, errors.Errorf("config with secret name %s not found", secretName)
140143
}
141144

142-
return NewClientFromConf(conf)
145+
return NewClientFromConf(conf, nil)
143146
}
144147

145148
// NewClientFromConf creates a new Cloud Client form a map of strings to strings.
146-
func NewClientFromConf(conf Config) (Client, error) {
149+
func NewClientFromConf(conf Config, clientConfig *corev1.ConfigMap) (Client, error) {
147150
cacheMutex.Lock()
148151
defer cacheMutex.Unlock()
149152

150153
if clientCache == nil {
151-
clientCache = ttlcache.NewCache()
152-
clientCache.SetTTL(cacheExpiration)
153-
clientCache.SkipTtlExtensionOnHit(false)
154+
clientCache = newClientCache(clientConfig)
154155
}
155156

156157
clientCacheKey := generateClientCacheKey(conf)
@@ -189,7 +190,7 @@ func (c *client) NewClientInDomainAndAccount(domain string, account string) (Cli
189190
c.config.APIKey = user.APIKey
190191
c.config.SecretKey = user.SecretKey
191192

192-
return NewClientFromConf(c.config)
193+
return NewClientFromConf(c.config, nil)
193194
}
194195

195196
// NewClientFromCSAPIClient creates a client from a CloudStack-Go API client. Mostly used for testing.
@@ -201,3 +202,19 @@ func NewClientFromCSAPIClient(cs *cloudstack.CloudStackClient) Client {
201202
func generateClientCacheKey(conf Config) string {
202203
return fmt.Sprintf("%+v", conf)
203204
}
205+
206+
func newClientCache(clientConfig *corev1.ConfigMap) *ttlcache.Cache {
207+
clientCache := ttlcache.NewCache()
208+
var cacheTTL time.Duration
209+
if clientConfig != nil {
210+
if ttl, exists := clientConfig.Data[ClientCacheTTLKey]; exists {
211+
cacheTTL, _ = time.ParseDuration(ttl)
212+
}
213+
}
214+
if cacheTTL == 0 {
215+
cacheTTL = DefaultClientCacheTTL
216+
}
217+
clientCache.SetTTL(cacheTTL)
218+
clientCache.SkipTtlExtensionOnHit(false)
219+
return clientCache
220+
}

0 commit comments

Comments
 (0)