package datastore import ( "errors" "github.com/docker/docker/libnetwork/types" "github.com/docker/libkv/store" ) var ( // ErrNotImplemented exported ErrNotImplemented = errors.New("Functionality not implemented") ) // MockData exported type MockData struct { Data []byte Index uint64 } // MockStore exported type MockStore struct { db map[string]*MockData } // NewMockStore creates a Map backed Datastore that is useful for mocking func NewMockStore() *MockStore { db := make(map[string]*MockData) return &MockStore{db} } // Get the value at "key", returns the last modified index // to use in conjunction to CAS calls func (s *MockStore) Get(key string) (*store.KVPair, error) { mData := s.db[key] if mData == nil { return nil, nil } return &store.KVPair{Value: mData.Data, LastIndex: mData.Index}, nil } // Put a value at "key" func (s *MockStore) Put(key string, value []byte, options *store.WriteOptions) error { mData := s.db[key] if mData == nil { mData = &MockData{value, 0} } mData.Index = mData.Index + 1 s.db[key] = mData return nil } // Delete a value at "key" func (s *MockStore) Delete(key string) error { delete(s.db, key) return nil } // Exists checks that the key exists inside the store func (s *MockStore) Exists(key string) (bool, error) { _, ok := s.db[key] return ok, nil } // List gets a range of values at "directory" func (s *MockStore) List(prefix string) ([]*store.KVPair, error) { return nil, ErrNotImplemented } // DeleteTree deletes a range of values at "directory" func (s *MockStore) DeleteTree(prefix string) error { delete(s.db, prefix) return nil } // Watch a single key for modifications func (s *MockStore) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) { return nil, ErrNotImplemented } // WatchTree triggers a watch on a range of values at "directory" func (s *MockStore) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) { return nil, ErrNotImplemented } // NewLock exposed func (s *MockStore) NewLock(key string, options *store.LockOptions) (store.Locker, error) { return nil, ErrNotImplemented } // AtomicPut put a value at "key" if the key has not been // modified in the meantime, throws an error if this is the case func (s *MockStore) AtomicPut(key string, newValue []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) { mData := s.db[key] if previous == nil { if mData != nil { return false, nil, types.BadRequestErrorf("atomic put failed because key exists") } // Else OK. } else { if mData == nil { return false, nil, types.BadRequestErrorf("atomic put failed because key exists") } if mData != nil && mData.Index != previous.LastIndex { return false, nil, types.BadRequestErrorf("atomic put failed due to mismatched Index") } // Else OK. } err := s.Put(key, newValue, nil) if err != nil { return false, nil, err } return true, &store.KVPair{Key: key, Value: newValue, LastIndex: s.db[key].Index}, nil } // AtomicDelete deletes a value at "key" if the key has not // been modified in the meantime, throws an error if this is the case func (s *MockStore) AtomicDelete(key string, previous *store.KVPair) (bool, error) { mData := s.db[key] if mData != nil && mData.Index != previous.LastIndex { return false, types.BadRequestErrorf("atomic delete failed due to mismatched Index") } return true, s.Delete(key) } // Close closes the client connection func (s *MockStore) Close() { }