github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/storageregistry/storageregistry.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package storageregistry
    20  
    21  import (
    22  	"context"
    23  	"encoding/json"
    24  	"encoding/xml"
    25  	"fmt"
    26  
    27  	"github.com/BurntSushi/toml"
    28  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    29  	registrypb "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
    30  	typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
    31  	"github.com/cs3org/reva/v2/pkg/errtypes"
    32  	"github.com/cs3org/reva/v2/pkg/rgrpc"
    33  	"github.com/cs3org/reva/v2/pkg/rgrpc/status"
    34  	sdk "github.com/cs3org/reva/v2/pkg/sdk/common"
    35  	"github.com/cs3org/reva/v2/pkg/storage"
    36  	"github.com/cs3org/reva/v2/pkg/storage/registry/registry"
    37  	"github.com/mitchellh/mapstructure"
    38  	"github.com/rs/zerolog"
    39  	"google.golang.org/grpc"
    40  )
    41  
    42  func init() {
    43  	rgrpc.Register("storageregistry", New)
    44  }
    45  
    46  type service struct {
    47  	reg storage.Registry
    48  }
    49  
    50  func (s *service) Close() error {
    51  	return nil
    52  }
    53  
    54  func (s *service) UnprotectedEndpoints() []string {
    55  	return []string{}
    56  }
    57  
    58  func (s *service) Register(ss *grpc.Server) {
    59  	registrypb.RegisterRegistryAPIServer(ss, s)
    60  }
    61  
    62  type config struct {
    63  	Driver  string                            `mapstructure:"driver"`
    64  	Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
    65  }
    66  
    67  func (c *config) init() {
    68  	if c.Driver == "" {
    69  		c.Driver = "static"
    70  	}
    71  }
    72  
    73  // New creates a new StorageBrokerService
    74  func New(m map[string]interface{}, ss *grpc.Server, _ *zerolog.Logger) (rgrpc.Service, error) {
    75  	c, err := parseConfig(m)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	c.init()
    81  
    82  	reg, err := getRegistry(c)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	service := &service{
    88  		reg: reg,
    89  	}
    90  
    91  	return service, nil
    92  }
    93  
    94  func parseConfig(m map[string]interface{}) (*config, error) {
    95  	c := &config{}
    96  	if err := mapstructure.Decode(m, c); err != nil {
    97  		return nil, err
    98  	}
    99  	return c, nil
   100  }
   101  
   102  func getRegistry(c *config) (storage.Registry, error) {
   103  	if f, ok := registry.NewFuncs[c.Driver]; ok {
   104  		return f(c.Drivers[c.Driver])
   105  	}
   106  	return nil, errtypes.NotFound("driver not found: " + c.Driver)
   107  }
   108  
   109  func (s *service) ListStorageProviders(ctx context.Context, req *registrypb.ListStorageProvidersRequest) (*registrypb.ListStorageProvidersResponse, error) {
   110  	pinfos, err := s.reg.ListProviders(ctx, sdk.DecodeOpaqueMap(req.Opaque))
   111  	if err != nil {
   112  		return &registrypb.ListStorageProvidersResponse{
   113  			Status: status.NewInternal(ctx, "error getting list of storage providers"),
   114  		}, nil
   115  	}
   116  
   117  	res := &registrypb.ListStorageProvidersResponse{
   118  		Status:    status.NewOK(ctx),
   119  		Providers: pinfos,
   120  	}
   121  	return res, nil
   122  }
   123  
   124  func (s *service) GetStorageProviders(ctx context.Context, req *registrypb.GetStorageProvidersRequest) (*registrypb.GetStorageProvidersResponse, error) {
   125  	space, err := decodeSpace(req.Opaque)
   126  	if err != nil {
   127  		return &registrypb.GetStorageProvidersResponse{
   128  			Status: status.NewInvalid(ctx, err.Error()),
   129  		}, nil
   130  	}
   131  	p, err := s.reg.GetProvider(ctx, space)
   132  	if err != nil {
   133  		switch err.(type) {
   134  		case errtypes.IsNotFound:
   135  			return &registrypb.GetStorageProvidersResponse{
   136  				Status: status.NewNotFound(ctx, err.Error()),
   137  			}, nil
   138  		default:
   139  			return &registrypb.GetStorageProvidersResponse{
   140  				Status: status.NewInternal(ctx, "error finding storage provider"),
   141  			}, nil
   142  		}
   143  	}
   144  
   145  	res := &registrypb.GetStorageProvidersResponse{
   146  		Status:    status.NewOK(ctx),
   147  		Providers: []*registrypb.ProviderInfo{p},
   148  	}
   149  	return res, nil
   150  }
   151  
   152  func decodeSpace(o *typespb.Opaque) (*provider.StorageSpace, error) {
   153  	if entry, ok := o.Map["space"]; ok {
   154  		var unmarshal func([]byte, interface{}) error
   155  		switch entry.Decoder {
   156  		case "json":
   157  			unmarshal = json.Unmarshal
   158  		case "toml":
   159  			unmarshal = toml.Unmarshal
   160  		case "xml":
   161  			unmarshal = xml.Unmarshal
   162  		}
   163  
   164  		space := &provider.StorageSpace{}
   165  		return space, unmarshal(entry.Value, space)
   166  	}
   167  
   168  	return nil, fmt.Errorf("missing space in opaque property")
   169  }
   170  
   171  func (s *service) GetHome(ctx context.Context, req *registrypb.GetHomeRequest) (*registrypb.GetHomeResponse, error) {
   172  	res := &registrypb.GetHomeResponse{
   173  		Status: status.NewUnimplemented(ctx, nil, "getHome is no longer used. use List"),
   174  	}
   175  	return res, nil
   176  
   177  }