github.com/cs3org/reva/v2@v2.27.7/tests/integration/grpc/gateway_storageprovider_static_test.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 grpc_test 20 21 import ( 22 "context" 23 "os" 24 "path" 25 26 "google.golang.org/grpc/metadata" 27 28 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 29 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 30 rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 31 storagep "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 32 "github.com/cs3org/reva/v2/pkg/auth/scope" 33 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 34 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 35 jwt "github.com/cs3org/reva/v2/pkg/token/manager/jwt" 36 37 . "github.com/onsi/ginkgo/v2" 38 . "github.com/onsi/gomega" 39 ) 40 41 // This test suite tests the gprc gateway interface 42 // 43 // It uses the `startRevads` helper to spawn the according reva daemon and 44 // other dependencies like a userprovider if needed. 45 // It also sets up an authenticated context and a service client to the storage 46 // provider to be used in the assertion functions. 47 var _ = PDescribe("gateway using a static registry and a shard setup", func() { 48 // TODO: Static registry relies on gateway being not dumb at the moment. So these won't work anymore 49 // FIXME: Bring me back please! 50 var ( 51 dependencies = []RevadConfig{} 52 revads = map[string]*Revad{} 53 54 einsteinCtx context.Context 55 marieCtx context.Context 56 variables map[string]string 57 serviceClient gateway.GatewayAPIClient 58 marie = &userpb.User{ 59 Id: &userpb.UserId{ 60 Idp: "0.0.0.0:39000", 61 OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", 62 Type: userpb.UserType_USER_TYPE_PRIMARY, 63 }, 64 Username: "marie", 65 } 66 einstein = &userpb.User{ 67 Id: &userpb.UserId{ 68 Idp: "0.0.0.0:39000", 69 OpaqueId: "e4fb0282-fabf-4cff-b1ee-90bdc01c4eef", 70 Type: userpb.UserType_USER_TYPE_PRIMARY, 71 }, 72 Username: "einstein", 73 } 74 homeRef = &storagep.Reference{Path: "."} 75 ) 76 77 BeforeEach(func() { 78 dependencies = []RevadConfig{ 79 {Name: "gateway", Config: "gateway-static.toml"}, 80 {Name: "users", Config: "userprovider-json.toml"}, 81 {Name: "storage", Config: "storageprovider-local.toml"}, 82 {Name: "storage2", Config: "storageprovider-local.toml"}, 83 } 84 redisAddress := os.Getenv("REDIS_ADDRESS") 85 if redisAddress == "" { 86 Fail("REDIS_ADDRESS not set") 87 } 88 variables = map[string]string{ 89 "redis_address": redisAddress, 90 } 91 }) 92 93 JustBeforeEach(func() { 94 var err error 95 einsteinCtx = context.Background() 96 marieCtx = context.Background() 97 98 // Add auth token 99 tokenManager, err := jwt.New(map[string]interface{}{"secret": "changemeplease"}) 100 Expect(err).ToNot(HaveOccurred()) 101 scope, err := scope.AddOwnerScope(nil) 102 Expect(err).ToNot(HaveOccurred()) 103 104 t, err := tokenManager.MintToken(marieCtx, marie, scope) 105 Expect(err).ToNot(HaveOccurred()) 106 marieCtx = ctxpkg.ContextSetToken(marieCtx, t) 107 marieCtx = metadata.AppendToOutgoingContext(marieCtx, ctxpkg.TokenHeader, t) 108 marieCtx = ctxpkg.ContextSetUser(marieCtx, marie) 109 110 t, err = tokenManager.MintToken(einsteinCtx, einstein, scope) 111 Expect(err).ToNot(HaveOccurred()) 112 einsteinCtx = ctxpkg.ContextSetToken(einsteinCtx, t) 113 einsteinCtx = metadata.AppendToOutgoingContext(einsteinCtx, ctxpkg.TokenHeader, t) 114 einsteinCtx = ctxpkg.ContextSetUser(einsteinCtx, einstein) 115 116 revads, err = startRevads(dependencies, variables) 117 Expect(err).ToNot(HaveOccurred()) 118 Expect(revads["gateway"]).ToNot(BeNil()) 119 serviceClient, err = pool.GetGatewayServiceClient(revads["gateway"].GrpcAddress) 120 Expect(err).ToNot(HaveOccurred()) 121 }) 122 123 AfterEach(func() { 124 for _, r := range revads { 125 Expect(r.Cleanup(CurrentGinkgoTestDescription().Failed)).To(Succeed()) 126 } 127 }) 128 129 Context("with a mapping based home jail", func() { 130 BeforeEach(func() { 131 variables["disable_home"] = "false" 132 }) 133 134 It("creates a home directory on the correct provider", func() { 135 By("creating marie's home") 136 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: homeRef}) 137 Expect(err).ToNot(HaveOccurred()) 138 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 139 140 res, err := serviceClient.CreateHome(marieCtx, &storagep.CreateHomeRequest{}) 141 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 142 Expect(err).ToNot(HaveOccurred()) 143 144 statRes, err = serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: homeRef}) 145 Expect(err).ToNot(HaveOccurred()) 146 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 147 148 // the mapping considers the opaque id: f... -> storage2 149 fi, err := os.Stat(path.Join(revads["storage2"].StorageRoot, "data/f", marie.Id.OpaqueId)) 150 Expect(err).ToNot(HaveOccurred()) 151 Expect(fi.IsDir()).To(BeTrue()) 152 _, err = os.Stat(path.Join(revads["storage"].StorageRoot, "data/f", marie.Id.OpaqueId)) 153 Expect(err).To(HaveOccurred()) 154 155 ghRes, err := serviceClient.GetHome(marieCtx, &storagep.GetHomeRequest{}) 156 Expect(err).ToNot(HaveOccurred()) 157 Expect(ghRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 158 159 By("creating einstein's home") 160 statRes, err = serviceClient.Stat(einsteinCtx, &storagep.StatRequest{Ref: homeRef}) 161 Expect(err).ToNot(HaveOccurred()) 162 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 163 164 res, err = serviceClient.CreateHome(einsteinCtx, &storagep.CreateHomeRequest{}) 165 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 166 Expect(err).ToNot(HaveOccurred()) 167 168 statRes, err = serviceClient.Stat(einsteinCtx, &storagep.StatRequest{Ref: homeRef}) 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 171 172 // the mapping considers the opaque id: e... -> storage 173 fi, err = os.Stat(path.Join(revads["storage"].StorageRoot, "data/e", einstein.Id.OpaqueId)) 174 Expect(err).ToNot(HaveOccurred()) 175 Expect(fi.IsDir()).To(BeTrue()) 176 _, err = os.Stat(path.Join(revads["storage2"].StorageRoot, "data/e", einstein.Id.OpaqueId)) 177 Expect(err).To(HaveOccurred()) 178 179 ghRes, err = serviceClient.GetHome(einsteinCtx, &storagep.GetHomeRequest{}) 180 Expect(err).ToNot(HaveOccurred()) 181 Expect(ghRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 182 }) 183 184 Context("with a home directory", func() { 185 JustBeforeEach(func() { 186 res, err := serviceClient.CreateHome(marieCtx, &storagep.CreateHomeRequest{}) 187 Expect(err).ToNot(HaveOccurred()) 188 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 189 }) 190 191 It("creates and lists a new directory", func() { 192 newRef := &storagep.Reference{Path: "/home/newdir"} 193 194 listRes, err := serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: homeRef}) 195 Expect(err).ToNot(HaveOccurred()) 196 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 197 Expect(len(listRes.Infos)).To(Equal(1)) 198 Expect(listRes.Infos[0].Path).To(Equal("/home/MyShares")) 199 200 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: newRef}) 201 Expect(err).ToNot(HaveOccurred()) 202 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 203 204 res, err := serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{Ref: newRef}) 205 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 206 Expect(err).ToNot(HaveOccurred()) 207 208 statRes, err = serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: newRef}) 209 Expect(err).ToNot(HaveOccurred()) 210 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 211 212 listRes, err = serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: homeRef}) 213 Expect(err).ToNot(HaveOccurred()) 214 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 215 Expect(len(listRes.Infos)).To(Equal(2)) 216 paths := []string{} 217 for _, i := range listRes.Infos { 218 paths = append(paths, i.Path) 219 } 220 Expect(paths).To(ConsistOf("/home/MyShares", newRef.Path)) 221 222 listRes, err = serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: newRef}) 223 Expect(err).ToNot(HaveOccurred()) 224 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 225 }) 226 227 Context("and a subdirectory", func() { 228 var ( 229 subdirRef = &storagep.Reference{Path: "/home/subdir"} 230 ) 231 232 JustBeforeEach(func() { 233 createRes, err := serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{Ref: subdirRef}) 234 Expect(createRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 235 Expect(err).ToNot(HaveOccurred()) 236 }) 237 238 It("gets the path to an ID", func() { 239 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: subdirRef}) 240 Expect(err).ToNot(HaveOccurred()) 241 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 242 243 getPathRes, err := serviceClient.GetPath(marieCtx, &storagep.GetPathRequest{ResourceId: statRes.Info.Id}) 244 Expect(err).ToNot(HaveOccurred()) 245 Expect(getPathRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 246 }) 247 248 It("stats by path and by ID", func() { 249 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: subdirRef}) 250 Expect(err).ToNot(HaveOccurred()) 251 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 252 253 idRef := &storagep.Reference{ResourceId: &storagep.ResourceId{StorageId: revads["storage2"].ID, OpaqueId: statRes.Info.Id.OpaqueId}} 254 statRes, err = serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: idRef}) 255 Expect(err).ToNot(HaveOccurred()) 256 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 257 }) 258 259 It("moves and deletes a directory", func() { 260 newRef2 := &storagep.Reference{Path: "/home/newdir2"} 261 262 moveRes, err := serviceClient.Move(marieCtx, &storagep.MoveRequest{Source: subdirRef, Destination: newRef2}) 263 Expect(err).ToNot(HaveOccurred()) 264 Expect(moveRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 265 266 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: newRef2}) 267 Expect(err).ToNot(HaveOccurred()) 268 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 269 270 deleteRes, err := serviceClient.Delete(marieCtx, &storagep.DeleteRequest{Ref: newRef2}) 271 Expect(deleteRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 272 Expect(err).ToNot(HaveOccurred()) 273 274 statRes, err = serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: newRef2}) 275 Expect(err).ToNot(HaveOccurred()) 276 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 277 }) 278 }) 279 }) 280 }) 281 282 Context("with a sharded /users mount", func() { 283 var ( 284 homePath = "/users/f/f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c" 285 rootRef = &storagep.Reference{Path: path.Join("/users")} 286 baseRef = &storagep.Reference{Path: path.Join("/users/f")} 287 homeRef = &storagep.Reference{Path: homePath} 288 subdirRef = &storagep.Reference{Path: path.Join(homePath, "subdir")} 289 ) 290 291 BeforeEach(func() { 292 variables["disable_home"] = "true" 293 }) 294 295 It("merges the results of both /users providers", func() { 296 lRes, err := serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: &storagep.Reference{Path: "/users"}}) 297 Expect(err).ToNot(HaveOccurred()) 298 Expect(lRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 299 Expect(len(lRes.Infos)).To(Equal(36)) 300 301 lRes, err = serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: &storagep.Reference{Path: "/users/f"}}) 302 Expect(err).ToNot(HaveOccurred()) 303 Expect(lRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 304 Expect(len(lRes.Infos)).To(Equal(0)) 305 306 res, err := serviceClient.CreateContainer(einsteinCtx, &storagep.CreateContainerRequest{ 307 Ref: &storagep.Reference{ 308 Path: path.Join("/users/e"), 309 }, 310 }) 311 Expect(err).ToNot(HaveOccurred()) 312 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 313 314 res, err = serviceClient.CreateContainer(einsteinCtx, &storagep.CreateContainerRequest{ 315 Ref: &storagep.Reference{ 316 Path: path.Join("/users/e", einstein.Id.OpaqueId), 317 }, 318 }) 319 Expect(err).ToNot(HaveOccurred()) 320 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 321 322 lRes, err = serviceClient.ListContainer(einsteinCtx, &storagep.ListContainerRequest{Ref: &storagep.Reference{Path: "/users/e"}}) 323 Expect(err).ToNot(HaveOccurred()) 324 Expect(lRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 325 Expect(len(lRes.Infos)).To(Equal(1)) 326 Expect(lRes.Infos[0].Path).To(Equal("/users/e/e4fb0282-fabf-4cff-b1ee-90bdc01c4eef")) 327 328 lRes, err = serviceClient.ListContainer(einsteinCtx, &storagep.ListContainerRequest{Ref: &storagep.Reference{Path: "/users/d"}}) 329 Expect(err).ToNot(HaveOccurred()) 330 Expect(lRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 331 Expect(len(lRes.Infos)).To(Equal(0)) 332 333 res, err = serviceClient.CreateContainer(einsteinCtx, &storagep.CreateContainerRequest{ 334 Ref: &storagep.Reference{ 335 Path: path.Join("/users/f"), 336 }, 337 }) 338 Expect(err).ToNot(HaveOccurred()) 339 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 340 341 res, err = serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{ 342 Ref: &storagep.Reference{ 343 Path: path.Join("/users/f", marie.Id.OpaqueId), 344 }, 345 }) 346 Expect(err).ToNot(HaveOccurred()) 347 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 348 349 lRes, err = serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: &storagep.Reference{Path: "/users/f"}}) 350 Expect(err).ToNot(HaveOccurred()) 351 Expect(lRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 352 Expect(len(lRes.Infos)).To(Equal(1)) 353 Expect(lRes.Infos[0].Path).To(Equal("/users/f/f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c")) 354 }) 355 356 Context("with a user home", func() { 357 JustBeforeEach(func() { 358 res, err := serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{ 359 Ref: &storagep.Reference{ 360 Path: path.Join("/users/f"), 361 }, 362 }) 363 Expect(err).ToNot(HaveOccurred()) 364 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 365 res, err = serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{ 366 Ref: &storagep.Reference{ 367 Path: path.Join("/users/f", marie.Id.OpaqueId), 368 }, 369 }) 370 Expect(err).ToNot(HaveOccurred()) 371 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 372 }) 373 374 It("provides access to the user home", func() { 375 newRef := &storagep.Reference{Path: path.Join(homePath, "newName")} 376 377 createRes, err := serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{Ref: subdirRef}) 378 Expect(createRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 379 Expect(err).ToNot(HaveOccurred()) 380 381 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: homeRef}) 382 Expect(err).ToNot(HaveOccurred()) 383 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 384 Expect(statRes.Info.Path).To(Equal(homePath)) 385 386 lRes, err := serviceClient.ListContainer(marieCtx, &storagep.ListContainerRequest{Ref: homeRef}) 387 Expect(err).ToNot(HaveOccurred()) 388 Expect(lRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 389 Expect(len(lRes.Infos)).To(Equal(1)) 390 Expect(lRes.Infos[0].Path).To(Equal(subdirRef.Path)) 391 392 mRes, err := serviceClient.Move(marieCtx, &storagep.MoveRequest{Source: subdirRef, Destination: newRef}) 393 Expect(mRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 394 Expect(err).ToNot(HaveOccurred()) 395 396 dRes, err := serviceClient.Delete(marieCtx, &storagep.DeleteRequest{Ref: newRef}) 397 Expect(dRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 398 Expect(err).ToNot(HaveOccurred()) 399 400 statRes, err = serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: newRef}) 401 Expect(err).ToNot(HaveOccurred()) 402 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 403 }) 404 405 It("propagates the etag to the root", func() { 406 getEtag := func(r *storagep.Reference) string { 407 statRes, err := serviceClient.Stat(marieCtx, &storagep.StatRequest{Ref: r}) 408 Expect(err).ToNot(HaveOccurred()) 409 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 410 return statRes.Info.Etag 411 } 412 413 rootEtag := getEtag(rootRef) 414 baseEtag := getEtag(baseRef) 415 userEtag := getEtag(homeRef) 416 417 createRes, err := serviceClient.CreateContainer(marieCtx, &storagep.CreateContainerRequest{Ref: subdirRef}) 418 Expect(err).ToNot(HaveOccurred()) 419 Expect(createRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 420 421 Expect(getEtag(homeRef)).ToNot(Equal(userEtag)) 422 Expect(getEtag(baseRef)).ToNot(Equal(baseEtag)) 423 Expect(getEtag(rootRef)).ToNot(Equal(rootEtag)) 424 }) 425 }) 426 }) 427 })