generated from kyma-project/template-repository
-
Notifications
You must be signed in to change notification settings - Fork 18
/
cache.go
142 lines (118 loc) · 4.01 KB
/
cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package chart
import (
"context"
"sync"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/json"
"sigs.k8s.io/controller-runtime/pkg/client"
)
var (
_ ManifestCache = (*inMemoryManifestCache)(nil)
_ ManifestCache = (*secretManifestCache)(nil)
)
var (
emptyServerlessSpecManifest = ServerlessSpecManifest{}
)
type ManifestCache interface {
Set(context.Context, client.ObjectKey, ServerlessSpecManifest) error
Get(context.Context, client.ObjectKey) (ServerlessSpecManifest, error)
Delete(context.Context, client.ObjectKey) error
}
// inMemoryManifestCache provides an in-memory processor to store serverless Spec and rendered chart manifest. By using sync.Map for caching,
// concurrent operations to the processor from diverse reconciliations are considered safe.
//
// Inside the processor is stored chart manifest with used custom flags by client.ObjectKey key.
type inMemoryManifestCache struct {
processor sync.Map
}
// NewInMemoryManifestCache returns a new instance of inMemoryManifestCache.
func NewInMemoryManifestCache() *inMemoryManifestCache {
return &inMemoryManifestCache{
processor: sync.Map{},
}
}
// Get loads the ServerlessSpecManifest from inMemoryManifestCache for the passed client.ObjectKey.
func (r *inMemoryManifestCache) Get(_ context.Context, key client.ObjectKey) (ServerlessSpecManifest, error) {
value, ok := r.processor.Load(key)
if !ok {
return emptyServerlessSpecManifest, nil
}
return *value.(*ServerlessSpecManifest), nil
}
// Set saves the passed flags and manifest into inMemoryManifestCache for the client.ObjectKey.
func (r *inMemoryManifestCache) Set(_ context.Context, key client.ObjectKey, spec ServerlessSpecManifest) error {
r.processor.Store(key, &spec)
return nil
}
// Delete deletes flags and manifest from inMemoryManifestCache for the passed client.ObjectKey.
func (r *inMemoryManifestCache) Delete(_ context.Context, key client.ObjectKey) error {
r.processor.Delete(key)
return nil
}
// secretManifestCache - provides an Secret based processor to store serverless Spec and rendered chart manifest.
//
// Inside the secret we store manifest and flags used to render it.
type secretManifestCache struct {
client client.Client
}
type ServerlessSpecManifest struct {
ManagerUID string
CustomFlags map[string]interface{}
Manifest string
}
// NewSecretManifestCache - returns a new instance of SecretManifestCache.
func NewSecretManifestCache(client client.Client) *secretManifestCache {
return &secretManifestCache{
client: client,
}
}
// Delete - removes Secret cache based on the passed client.ObjectKey.
func (m *secretManifestCache) Delete(ctx context.Context, key client.ObjectKey) error {
err := m.client.Delete(ctx, &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
})
return client.IgnoreNotFound(err)
}
// Get - loads the ServerlessSpecManifest from SecretManifestCache based on the passed client.ObjectKey.
func (m *secretManifestCache) Get(ctx context.Context, key client.ObjectKey) (ServerlessSpecManifest, error) {
secret := corev1.Secret{}
err := m.client.Get(ctx, key, &secret)
if errors.IsNotFound(err) {
return emptyServerlessSpecManifest, nil
}
if err != nil {
return emptyServerlessSpecManifest, err
}
spec := ServerlessSpecManifest{}
err = json.Unmarshal(secret.Data["spec"], &spec)
if err != nil {
return emptyServerlessSpecManifest, err
}
return spec, nil
}
// Set - saves the passed flags and manifest into Secret based on the client.ObjectKey.
func (m *secretManifestCache) Set(ctx context.Context, key client.ObjectKey, spec ServerlessSpecManifest) error {
byteSpec, err := json.Marshal(&spec)
if err != nil {
return err
}
secret := corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Data: map[string][]byte{
"spec": byteSpec,
},
}
err = m.client.Update(ctx, &secret)
if !errors.IsNotFound(err) {
return err
}
return m.client.Create(ctx, &secret)
}