diff --git a/storage/memory/static_clients_test.go b/storage/memory/static_clients_test.go new file mode 100644 index 00000000..e34b070c --- /dev/null +++ b/storage/memory/static_clients_test.go @@ -0,0 +1,48 @@ +package memory + +import ( + "reflect" + "testing" + + "github.com/coreos/poke/storage" +) + +func TestStaticClients(t *testing.T) { + s := New() + + c1 := storage.Client{ID: "foo", Secret: "foo_secret"} + c2 := storage.Client{ID: "bar", Secret: "bar_secret"} + s.CreateClient(c1) + s2 := storage.WithStaticClients(s, []storage.Client{c2}) + + tests := []struct { + id string + s storage.Storage + wantErr bool + wantClient storage.Client + }{ + {"foo", s, false, c1}, + {"bar", s, true, storage.Client{}}, + {"foo", s2, true, storage.Client{}}, + {"bar", s2, false, c2}, + } + + for i, tc := range tests { + gotClient, err := tc.s.GetClient(tc.id) + if err != nil { + if !tc.wantErr { + t.Errorf("case %d: GetClient(%q) %v", i, tc.id, err) + } + continue + } + + if tc.wantErr { + t.Errorf("case %d: GetClient(%q) expected error", i, tc.id) + continue + } + + if !reflect.DeepEqual(tc.wantClient, gotClient) { + t.Errorf("case %d: expected=%#v got=%#v", i, tc.wantClient, gotClient) + } + } +} diff --git a/storage/static_clients.go b/storage/static_clients.go new file mode 100644 index 00000000..d7932393 --- /dev/null +++ b/storage/static_clients.go @@ -0,0 +1,55 @@ +package storage + +import "errors" + +// Tests for this code are in the "memory" package, since this package doesn't +// define a concrete storage implementation. + +// staticClientsStorage is a storage that only allow read-only actions on clients. +// All read actions return from the list of clients stored in memory, not the +// underlying +type staticClientsStorage struct { + Storage + + // A read-only set of clients. + clients []Client + clientsByID map[string]Client +} + +// WithStaticClients returns a storage with a read-only set of clients. Write actions, +// such as creating other clients, will fail. +// +// In the future the returned storage may allow creating and storing additional clients +// in the underlying storage. +func WithStaticClients(s Storage, staticClients []Client) Storage { + clientsByID := make(map[string]Client, len(staticClients)) + for _, client := range staticClients { + clientsByID[client.ID] = client + } + return staticClientsStorage{s, staticClients, clientsByID} +} + +func (s staticClientsStorage) GetClient(id string) (Client, error) { + if client, ok := s.clientsByID[id]; ok { + return client, nil + } + return Client{}, ErrNotFound +} + +func (s staticClientsStorage) ListClients() ([]Client, error) { + clients := make([]Client, len(s.clients)) + copy(clients, s.clients) + return clients, nil +} + +func (s staticClientsStorage) CreateClient(c Client) error { + return errors.New("static clients: read-only cannot create client") +} + +func (s staticClientsStorage) DeleteClient(id string) error { + return errors.New("static clients: read-only cannot delete client") +} + +func (s staticClientsStorage) UpdateClient(id string, updater func(old Client) (Client, error)) error { + return errors.New("static clients: read-only cannot update client") +}