github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/storage/driver/memory.go (about) 1 /* 2 Copyright The Helm Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package driver 18 19 import ( 20 "strconv" 21 "strings" 22 "sync" 23 24 rspb "github.com/stefanmcshane/helm/pkg/release" 25 ) 26 27 var _ Driver = (*Memory)(nil) 28 29 const ( 30 // MemoryDriverName is the string name of this driver. 31 MemoryDriverName = "Memory" 32 33 defaultNamespace = "default" 34 ) 35 36 // A map of release names to list of release records 37 type memReleases map[string]records 38 39 // Memory is the in-memory storage driver implementation. 40 type Memory struct { 41 sync.RWMutex 42 namespace string 43 // A map of namespaces to releases 44 cache map[string]memReleases 45 } 46 47 // NewMemory initializes a new memory driver. 48 func NewMemory() *Memory { 49 return &Memory{cache: map[string]memReleases{}, namespace: "default"} 50 } 51 52 // SetNamespace sets a specific namespace in which releases will be accessed. 53 // An empty string indicates all namespaces (for the list operation) 54 func (mem *Memory) SetNamespace(ns string) { 55 mem.namespace = ns 56 } 57 58 // Name returns the name of the driver. 59 func (mem *Memory) Name() string { 60 return MemoryDriverName 61 } 62 63 // Get returns the release named by key or returns ErrReleaseNotFound. 64 func (mem *Memory) Get(key string) (*rspb.Release, error) { 65 defer unlock(mem.rlock()) 66 67 keyWithoutPrefix := strings.TrimPrefix(key, "sh.helm.release.v1.") 68 switch elems := strings.Split(keyWithoutPrefix, ".v"); len(elems) { 69 case 2: 70 name, ver := elems[0], elems[1] 71 if _, err := strconv.Atoi(ver); err != nil { 72 return nil, ErrInvalidKey 73 } 74 if recs, ok := mem.cache[mem.namespace][name]; ok { 75 if r := recs.Get(key); r != nil { 76 return r.rls, nil 77 } 78 } 79 return nil, ErrReleaseNotFound 80 default: 81 return nil, ErrInvalidKey 82 } 83 } 84 85 // List returns the list of all releases such that filter(release) == true 86 func (mem *Memory) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) { 87 defer unlock(mem.rlock()) 88 89 var ls []*rspb.Release 90 for namespace := range mem.cache { 91 if mem.namespace != "" { 92 // Should only list releases of this namespace 93 namespace = mem.namespace 94 } 95 for _, recs := range mem.cache[namespace] { 96 recs.Iter(func(_ int, rec *record) bool { 97 if filter(rec.rls) { 98 ls = append(ls, rec.rls) 99 } 100 return true 101 }) 102 } 103 if mem.namespace != "" { 104 // Should only list releases of this namespace 105 break 106 } 107 } 108 return ls, nil 109 } 110 111 // Query returns the set of releases that match the provided set of labels 112 func (mem *Memory) Query(keyvals map[string]string) ([]*rspb.Release, error) { 113 defer unlock(mem.rlock()) 114 115 var lbs labels 116 117 lbs.init() 118 lbs.fromMap(keyvals) 119 120 var ls []*rspb.Release 121 for namespace := range mem.cache { 122 if mem.namespace != "" { 123 // Should only query releases of this namespace 124 namespace = mem.namespace 125 } 126 for _, recs := range mem.cache[namespace] { 127 recs.Iter(func(_ int, rec *record) bool { 128 // A query for a release name that doesn't exist (has been deleted) 129 // can cause rec to be nil. 130 if rec == nil { 131 return false 132 } 133 if rec.lbs.match(lbs) { 134 ls = append(ls, rec.rls) 135 } 136 return true 137 }) 138 } 139 if mem.namespace != "" { 140 // Should only query releases of this namespace 141 break 142 } 143 } 144 145 if len(ls) == 0 { 146 return nil, ErrReleaseNotFound 147 } 148 149 return ls, nil 150 } 151 152 // Create creates a new release or returns ErrReleaseExists. 153 func (mem *Memory) Create(key string, rls *rspb.Release) error { 154 defer unlock(mem.wlock()) 155 156 // For backwards compatibility, we protect against an unset namespace 157 namespace := rls.Namespace 158 if namespace == "" { 159 namespace = defaultNamespace 160 } 161 mem.SetNamespace(namespace) 162 163 if _, ok := mem.cache[namespace]; !ok { 164 mem.cache[namespace] = memReleases{} 165 } 166 167 if recs, ok := mem.cache[namespace][rls.Name]; ok { 168 if err := recs.Add(newRecord(key, rls)); err != nil { 169 return err 170 } 171 mem.cache[namespace][rls.Name] = recs 172 return nil 173 } 174 mem.cache[namespace][rls.Name] = records{newRecord(key, rls)} 175 return nil 176 } 177 178 // Update updates a release or returns ErrReleaseNotFound. 179 func (mem *Memory) Update(key string, rls *rspb.Release) error { 180 defer unlock(mem.wlock()) 181 182 // For backwards compatibility, we protect against an unset namespace 183 namespace := rls.Namespace 184 if namespace == "" { 185 namespace = defaultNamespace 186 } 187 mem.SetNamespace(namespace) 188 189 if _, ok := mem.cache[namespace]; ok { 190 if rs, ok := mem.cache[namespace][rls.Name]; ok && rs.Exists(key) { 191 rs.Replace(key, newRecord(key, rls)) 192 return nil 193 } 194 } 195 return ErrReleaseNotFound 196 } 197 198 // Delete deletes a release or returns ErrReleaseNotFound. 199 func (mem *Memory) Delete(key string) (*rspb.Release, error) { 200 defer unlock(mem.wlock()) 201 202 keyWithoutPrefix := strings.TrimPrefix(key, "sh.helm.release.v1.") 203 elems := strings.Split(keyWithoutPrefix, ".v") 204 205 if len(elems) != 2 { 206 return nil, ErrInvalidKey 207 } 208 209 name, ver := elems[0], elems[1] 210 if _, err := strconv.Atoi(ver); err != nil { 211 return nil, ErrInvalidKey 212 } 213 if _, ok := mem.cache[mem.namespace]; ok { 214 if recs, ok := mem.cache[mem.namespace][name]; ok { 215 if r := recs.Remove(key); r != nil { 216 // recs.Remove changes the slice reference, so we have to re-assign it. 217 mem.cache[mem.namespace][name] = recs 218 return r.rls, nil 219 } 220 } 221 } 222 return nil, ErrReleaseNotFound 223 } 224 225 // wlock locks mem for writing 226 func (mem *Memory) wlock() func() { 227 mem.Lock() 228 return func() { mem.Unlock() } 229 } 230 231 // rlock locks mem for reading 232 func (mem *Memory) rlock() func() { 233 mem.RLock() 234 return func() { mem.RUnlock() } 235 } 236 237 // unlock calls fn which reverses a mem.rlock or mem.wlock. e.g: 238 // ```defer unlock(mem.rlock())```, locks mem for reading at the 239 // call point of defer and unlocks upon exiting the block. 240 func unlock(fn func()) { fn() }