github.com/cs3org/reva/v2@v2.27.7/pkg/storagespace/storagespace.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 storagespace 20 21 import ( 22 "path" 23 "strings" 24 25 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 26 "github.com/cs3org/reva/v2/pkg/utils" 27 "github.com/pkg/errors" 28 ) 29 30 const ( 31 _idDelimiter string = "!" 32 _storageIDDelimiter string = "$" 33 ) 34 35 var ( 36 // ErrInvalidSpaceReference signals that the space reference is invalid. 37 ErrInvalidSpaceReference = errors.New("invalid storage space reference") 38 // ErrInvalidSpaceID signals that the space ID is invalid. 39 ErrInvalidSpaceID = errors.New("invalid storage space id") 40 ) 41 42 // SplitID splits a storage space ID into a provider ID and a node ID. 43 // The accepted formats results of the storage space ID and respective results 44 // are: 45 // <storageid>$<spaceid>!<nodeid> -> <storageid>, <spaceid>, <nodeid> 46 // <storageid>$<spaceid> -> <storageid>, <spaceid>, "" 47 // <spaceid> -> "", <spaceid>, "" 48 func SplitID(ssid string) (storageid, spaceid, nodeid string, err error) { 49 if ssid == "" { 50 return "", "", "", errors.Wrap(ErrInvalidSpaceID, "can't split empty storage space ID") 51 } 52 53 storageid, snid := SplitStorageID(ssid) 54 parts := strings.SplitN(snid, _idDelimiter, 2) 55 if len(parts) == 1 || parts[1] == "" { 56 return storageid, parts[0], "", nil 57 } 58 59 return storageid, parts[0], parts[1], nil 60 } 61 62 // SplitStorageID splits a storage ID into the storage ID and the spaceID. 63 // The accepted formats are: 64 // <storageid>$<spaceid> -> <storageid>, <spaceid> 65 // <spaceid> -> "", <spaceid> 66 func SplitStorageID(sid string) (storageID, spaceID string) { 67 parts := strings.SplitN(sid, _storageIDDelimiter, 2) 68 if len(parts) == 2 { 69 return parts[0], parts[1] 70 } 71 return "", parts[0] 72 } 73 74 // FormatResourceID converts a ResourceId into the string format. 75 // The result format will look like: 76 // <storageid>$<spaceid>!<opaqueid> 77 func FormatResourceID(sid *provider.ResourceId) string { 78 if sid.GetOpaqueId() == "" { 79 return FormatStorageID(sid.GetStorageId(), sid.GetSpaceId()) 80 } 81 return strings.Join([]string{FormatStorageID(sid.StorageId, sid.SpaceId), sid.OpaqueId}, _idDelimiter) 82 } 83 84 // FormatStorageID converts the provider ID and space ID into the string format. 85 // The result format will look like: 86 // <storageid>$<spaceid> or 87 // <spaceid> in case the provider ID is empty. 88 func FormatStorageID(storageID, spaceID string) string { 89 if storageID == "" { 90 return spaceID 91 } 92 return strings.Join([]string{storageID, spaceID}, _storageIDDelimiter) 93 } 94 95 // ParseID parses a storage space ID and returns a storageprovider ResourceId. 96 // The accepted formats are: 97 // <providerid>$<spaceid>!<nodeid> -> <providerid>$<spaceid>, <nodeid> 98 // <providerid>$<spaceid> -> <providerid>$<spaceid>, <spaceid> 99 // <spaceid> -> <spaceid>, <spaceid> 100 func ParseID(ssid string) (provider.ResourceId, error) { 101 sid, spid, oid, err := SplitID(ssid) 102 return provider.ResourceId{ 103 StorageId: sid, 104 SpaceId: spid, 105 OpaqueId: oid, 106 }, err 107 } 108 109 // ParseReference parses a string into a spaces reference. 110 // The expected format is `<providerid>$<spaceid>!<nodeid>/<path>`. 111 func ParseReference(sRef string) (provider.Reference, error) { 112 parts := strings.SplitN(sRef, "/", 2) 113 114 rid, err := ParseID(parts[0]) 115 if err != nil { 116 return provider.Reference{}, err 117 } 118 119 var path string 120 if len(parts) == 2 { 121 path = parts[1] 122 } 123 124 return provider.Reference{ 125 ResourceId: &rid, 126 Path: utils.MakeRelativePath(path), 127 }, nil 128 } 129 130 // FormatReference will format a storage space reference into a string representation. 131 // If ref or ref.ResourceId are nil an error will be returned. 132 // The function doesn't check if all values are set. 133 // The resulting format can be: 134 // 135 // "storage_id!opaque_id" 136 // "storage_id!opaque_id/path" 137 // "storage_id/path" 138 // "storage_id" 139 func FormatReference(ref *provider.Reference) (string, error) { 140 if ref == nil || ref.ResourceId == nil || ref.ResourceId.SpaceId == "" { 141 return "", ErrInvalidSpaceReference 142 } 143 ssid := FormatResourceID(ref.ResourceId) 144 return path.Join(ssid, ref.Path), nil 145 } 146 147 // UpdateLegacyResourceID checks if the given resource id contains a correct triple and will convert legacy ids without a spaceid 148 // by splitting the storageid. 149 func UpdateLegacyResourceID(id *provider.ResourceId) *provider.ResourceId { 150 if storageid, spaceid := SplitStorageID(id.StorageId); storageid != "" && id.SpaceId == "" { 151 return &provider.ResourceId{ 152 StorageId: storageid, 153 SpaceId: spaceid, 154 OpaqueId: id.OpaqueId, 155 } 156 } 157 return id 158 }