Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix spaces stat requests #2501

Merged
merged 1 commit into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions changelog/unreleased/spaces-stat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Fix spaces stat

When stating a space e.g. the Share Jail and that space contains another space, in this case a share
then the stat would sometimes get the sub space instead of the Share Jail itself.

https://github.com/cs3org/reva/pull/2501
62 changes: 61 additions & 1 deletion internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide
// Stat returns the Resoure info for a given resource by forwarding the request to the responsible provider.
// TODO cache info
func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) {
c, _, ref, err := s.findAndUnwrap(ctx, req.Ref)
c, _, ref, err := s.findAndUnwrapUnique(ctx, req.Ref)
if err != nil {
return &provider.StatResponse{
Status: status.NewNotFound(ctx, fmt.Sprintf("gateway could not find space for ref=%+v", req.Ref)),
Expand Down Expand Up @@ -991,6 +991,16 @@ func (s *svc) find(ctx context.Context, ref *provider.Reference) (provider.Provi
return client, p[0], err
}

func (s *svc) findUnique(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, error) {
p, err := s.findSingleSpace(ctx, ref)
if err != nil {
return nil, nil, err
}

client, err := s.getStorageProviderClient(ctx, p[0])
return client, p[0], err
}

// FIXME findAndUnwrap currently just returns the first provider ... which may not be what is needed.
// for the ListRecycle call we need an exact match, for Stat and List we need to query all related providers
func (s *svc) findAndUnwrap(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, *provider.Reference, error) {
Expand All @@ -1014,6 +1024,27 @@ func (s *svc) findAndUnwrap(ctx context.Context, ref *provider.Reference) (provi
return c, p, relativeReference, nil
}

func (s *svc) findAndUnwrapUnique(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, *provider.Reference, error) {
c, p, err := s.findUnique(ctx, ref)
if err != nil {
return nil, nil, nil, err
}

var (
root *provider.ResourceId
mountPath string
)
for _, space := range decodeSpaces(p) {
mountPath = decodePath(space)
root = space.Root
break // TODO can there be more than one space for a path?
}

relativeReference := unwrap(ref, mountPath, root)

return c, p, relativeReference, nil
}

func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderInfo) (provider.ProviderAPIClient, error) {
c, err := pool.GetStorageProviderServiceClient(p.Address)
if err != nil {
Expand Down Expand Up @@ -1060,6 +1091,35 @@ func (s *svc) findSpaces(ctx context.Context, ref *provider.Reference) ([]*regis
return s.findProvider(ctx, listReq)
}

func (s *svc) findSingleSpace(ctx context.Context, ref *provider.Reference) ([]*registry.ProviderInfo, error) {
switch {
case ref == nil:
return nil, errtypes.BadRequest("missing reference")
case ref.ResourceId != nil:
// no action needed in that case
case ref.Path != "": // TODO implement a mount path cache in the registry?
// nothing to do here either
default:
return nil, errtypes.BadRequest("invalid reference, at least path or id must be set")
}

filters := map[string]string{
"path": ref.Path,
"unique": "true",
}
if ref.ResourceId != nil {
filters["storage_id"] = ref.ResourceId.StorageId
filters["opaque_id"] = ref.ResourceId.OpaqueId
}

listReq := &registry.ListStorageProvidersRequest{
Opaque: &typesv1beta1.Opaque{},
}
sdk.EncodeOpaqueMap(listReq.Opaque, filters)

return s.findProvider(ctx, listReq)
}

func (s *svc) findProvider(ctx context.Context, listReq *registry.ListStorageProvidersRequest) ([]*registry.ProviderInfo, error) {
// lookup
c, err := pool.GetStorageRegistryClient(s.c.StorageRegistryEndpoint)
Expand Down