Skip to content

Commit ecfcbde

Browse files
authored
ffs/manager: list instances (textileio#383)
* fix close Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * ffs/manager: add List() Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * proto files Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * rebase Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * add ListAPI to client Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * lints Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
1 parent 821686a commit ecfcbde

8 files changed

Lines changed: 384 additions & 161 deletions

File tree

api/client/ffs.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
cid "github.com/ipfs/go-cid"
9+
"github.com/textileio/powergate/ffs"
910
ff "github.com/textileio/powergate/ffs"
1011
"github.com/textileio/powergate/ffs/api"
1112
"github.com/textileio/powergate/ffs/rpc"
@@ -91,6 +92,19 @@ func (f *FFS) Create(ctx context.Context) (string, string, error) {
9192
return r.ID, r.Token, nil
9293
}
9394

95+
// ListAPI returns a list of existing API instances.
96+
func (f *FFS) ListAPI(ctx context.Context) ([]ffs.APIID, error) {
97+
r, err := f.client.ListAPI(ctx, &rpc.ListAPIRequest{})
98+
if err != nil {
99+
return nil, err
100+
}
101+
res := make([]ff.APIID, len(r.Instances))
102+
for i, v := range r.Instances {
103+
res[i] = ff.APIID(v)
104+
}
105+
return res, nil
106+
}
107+
94108
// ID returns the FFS instance ID
95109
func (f *FFS) ID(ctx context.Context) (ff.APIID, error) {
96110
resp, err := f.client.ID(ctx, &rpc.IDRequest{})

ffs/auth/auth.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/google/uuid"
1010
ds "github.com/ipfs/go-datastore"
11+
"github.com/ipfs/go-datastore/query"
1112
logging "github.com/ipfs/go-log/v2"
1213
"github.com/textileio/powergate/ffs"
1314
)
@@ -78,6 +79,32 @@ func (r *Auth) Get(token string) (ffs.APIID, error) {
7879
return e.APIID, nil
7980
}
8081

82+
// List returns a list of all API instances.
83+
func (r *Auth) List() ([]ffs.APIID, error) {
84+
r.lock.Lock()
85+
defer r.lock.Unlock()
86+
q := query.Query{Prefix: ""}
87+
res, err := r.ds.Query(q)
88+
if err != nil {
89+
return nil, fmt.Errorf("executing query in datastore: %s", err)
90+
}
91+
defer func() {
92+
if err := res.Close(); err != nil {
93+
log.Errorf("closing query result: %s", err)
94+
}
95+
}()
96+
97+
var ret []ffs.APIID
98+
for r := range res.Next() {
99+
var e entry
100+
if err := json.Unmarshal(r.Entry.Value, &e); err != nil {
101+
return nil, fmt.Errorf("unmarshaling query result: %s", err)
102+
}
103+
ret = append(ret, e.APIID)
104+
}
105+
return ret, nil
106+
}
107+
81108
func makeKey(token string) ds.Key {
82109
return dsBase.ChildString(token)
83110
}

ffs/manager/manager.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"fmt"
77
"sync"
88

9-
ds "github.com/ipfs/go-datastore"
9+
"github.com/ipfs/go-datastore"
1010
"github.com/ipfs/go-datastore/namespace"
1111
logging "github.com/ipfs/go-log/v2"
1212
"github.com/textileio/powergate/ffs"
@@ -22,7 +22,7 @@ var (
2222
createDefConfig sync.Once
2323
defCidConfig ffs.DefaultConfig
2424

25-
istoreNamespace = ds.NewKey("ffs/api/istore")
25+
istoreNamespace = datastore.NewKey("ffs/api/istore")
2626

2727
log = logging.Logger("ffs-manager")
2828
)
@@ -33,17 +33,17 @@ type Manager struct {
3333
sched ffs.Scheduler
3434

3535
lock sync.Mutex
36-
ds ds.Datastore
36+
ds datastore.Datastore
3737
auth *auth.Auth
3838
instances map[ffs.APIID]*api.API
3939

4040
closed bool
4141
}
4242

4343
// New returns a new Manager.
44-
func New(ds ds.Datastore, wm ffs.WalletManager, sched ffs.Scheduler) (*Manager, error) {
44+
func New(ds datastore.Datastore, wm ffs.WalletManager, sched ffs.Scheduler) (*Manager, error) {
4545
return &Manager{
46-
auth: auth.New(ds),
46+
auth: auth.New(namespace.Wrap(ds, datastore.NewKey("auth"))),
4747
ds: ds,
4848
wm: wm,
4949
sched: sched,
@@ -92,6 +92,18 @@ func (m *Manager) Create(ctx context.Context) (ffs.APIID, string, error) {
9292
return fapi.ID(), auth, nil
9393
}
9494

95+
// List returns a list of all existing API instances.
96+
func (m *Manager) List() ([]ffs.APIID, error) {
97+
m.lock.Lock()
98+
defer m.lock.Unlock()
99+
100+
res, err := m.auth.List()
101+
if err != nil {
102+
return nil, fmt.Errorf("listing existing instances: %s", err)
103+
}
104+
return res, nil
105+
}
106+
95107
// GetByAuthToken loads an existing instance using an auth-token. If auth-token doesn't exist,
96108
// it returns ErrAuthTokenNotFound.
97109
func (m *Manager) GetByAuthToken(token string) (*api.API, error) {

ffs/manager/manager_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,34 @@ func TestCreate(t *testing.T) {
4141
require.True(t, id.Valid())
4242
}
4343

44+
func TestList(t *testing.T) {
45+
t.Parallel()
46+
ds := tests.NewTxMapDatastore()
47+
ctx := context.Background()
48+
m, cls := newManager(t, ds)
49+
defer cls()
50+
51+
lst, err := m.List()
52+
require.Nil(t, err)
53+
require.Equal(t, 0, len(lst))
54+
55+
id1, _, err := m.Create(ctx)
56+
require.Nil(t, err)
57+
lst, err = m.List()
58+
require.Nil(t, err)
59+
require.Equal(t, 1, len(lst))
60+
require.Contains(t, lst, id1)
61+
62+
id2, _, err := m.Create(ctx)
63+
require.Nil(t, err)
64+
65+
lst, err = m.List()
66+
require.Nil(t, err)
67+
require.Contains(t, lst, id1)
68+
require.Contains(t, lst, id2)
69+
require.Equal(t, 2, len(lst))
70+
}
71+
4472
func TestGetByAuthToken(t *testing.T) {
4573
t.Parallel()
4674
ds := tests.NewTxMapDatastore()

0 commit comments

Comments
 (0)