mirror of https://github.com/docker/docs.git
110 lines
2.5 KiB
Go
110 lines
2.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type key struct {
|
|
algorithm string
|
|
public []byte
|
|
}
|
|
|
|
type ver struct {
|
|
version int
|
|
data []byte
|
|
}
|
|
|
|
// MemStorage is really just designed for dev and testing. It is very
|
|
// inefficient in many scenarios
|
|
type MemStorage struct {
|
|
lock sync.Mutex
|
|
tufMeta map[string][]*ver
|
|
tsKeys map[string]*key
|
|
}
|
|
|
|
// NewMemStorage instantiates a memStorage instance
|
|
func NewMemStorage() *MemStorage {
|
|
return &MemStorage{
|
|
tufMeta: make(map[string][]*ver),
|
|
tsKeys: make(map[string]*key),
|
|
}
|
|
}
|
|
|
|
// UpdateCurrent updates the meta data for a specific role
|
|
func (st *MemStorage) UpdateCurrent(gun string, update MetaUpdate) error {
|
|
id := entryKey(gun, update.Role)
|
|
st.lock.Lock()
|
|
defer st.lock.Unlock()
|
|
if space, ok := st.tufMeta[id]; ok {
|
|
for _, v := range space {
|
|
if v.version >= update.Version {
|
|
return &ErrOldVersion{}
|
|
}
|
|
}
|
|
}
|
|
st.tufMeta[id] = append(st.tufMeta[id], &ver{version: update.Version, data: update.Data})
|
|
return nil
|
|
}
|
|
|
|
// UpdateMany updates multiple TUF records
|
|
func (st *MemStorage) UpdateMany(gun string, updates []MetaUpdate) error {
|
|
for _, u := range updates {
|
|
st.UpdateCurrent(gun, u)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetCurrent returns the metadada for a given role, under a GUN
|
|
func (st *MemStorage) GetCurrent(gun, role string) (data []byte, err error) {
|
|
id := entryKey(gun, role)
|
|
st.lock.Lock()
|
|
defer st.lock.Unlock()
|
|
space, ok := st.tufMeta[id]
|
|
if !ok || len(space) == 0 {
|
|
return nil, &ErrNotFound{}
|
|
}
|
|
return space[len(space)-1].data, nil
|
|
}
|
|
|
|
// Delete delets all the metadata for a given GUN
|
|
func (st *MemStorage) Delete(gun string) error {
|
|
st.lock.Lock()
|
|
defer st.lock.Unlock()
|
|
for k := range st.tufMeta {
|
|
if strings.HasPrefix(k, gun) {
|
|
delete(st.tufMeta, k)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetTimestampKey returns the public key material of the timestamp key of a given gun
|
|
func (st *MemStorage) GetTimestampKey(gun string) (algorithm string, public []byte, err error) {
|
|
// no need for lock. It's ok to return nil if an update
|
|
// wasn't observed
|
|
k, ok := st.tsKeys[gun]
|
|
if !ok {
|
|
return "", nil, &ErrNoKey{gun: gun}
|
|
}
|
|
|
|
return k.algorithm, k.public, nil
|
|
}
|
|
|
|
// SetTimestampKey sets a Timestamp key under a gun
|
|
func (st *MemStorage) SetTimestampKey(gun string, algorithm string, public []byte) error {
|
|
k := &key{algorithm: algorithm, public: public}
|
|
st.lock.Lock()
|
|
defer st.lock.Unlock()
|
|
if _, ok := st.tsKeys[gun]; ok {
|
|
return &ErrTimestampKeyExists{gun: gun}
|
|
}
|
|
st.tsKeys[gun] = k
|
|
return nil
|
|
}
|
|
|
|
func entryKey(gun, role string) string {
|
|
return fmt.Sprintf("%s.%s", gun, role)
|
|
}
|