github.com/cs3org/reva/v2@v2.27.7/tests/integration/grpc/gateway_storageprovider_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 "time" 26 27 "github.com/cs3org/reva/v2/pkg/storagespace" 28 "github.com/rs/zerolog" 29 "google.golang.org/grpc/metadata" 30 31 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 32 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 33 rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 34 storagep "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 35 "github.com/cs3org/reva/v2/pkg/auth/scope" 36 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 37 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 38 "github.com/cs3org/reva/v2/pkg/storage" 39 "github.com/cs3org/reva/v2/pkg/storage/fs/ocis" 40 jwt "github.com/cs3org/reva/v2/pkg/token/manager/jwt" 41 "github.com/cs3org/reva/v2/pkg/utils" 42 "github.com/cs3org/reva/v2/tests/helpers" 43 44 . "github.com/onsi/ginkgo/v2" 45 . "github.com/onsi/gomega" 46 ) 47 48 // This test suite tests the gprc gateway interface 49 // 50 // It uses the `startRevads` helper to spawn the according reva daemon and 51 // other dependencies like a userprovider if needed. 52 // It also sets up an authenticated context and a service client to the storage 53 // provider to be used in the assertion functions. 54 var _ = Describe("gateway", func() { 55 var ( 56 dependencies = []RevadConfig{} 57 variables = map[string]string{} 58 revads = map[string]*Revad{} 59 60 ctx context.Context 61 serviceClient gateway.GatewayAPIClient 62 user = &userpb.User{ 63 Id: &userpb.UserId{ 64 Idp: "0.0.0.0:39000", 65 OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", 66 Type: userpb.UserType_USER_TYPE_PRIMARY, 67 }, 68 Username: "einstein", 69 } 70 homeRef = &storagep.Reference{ 71 ResourceId: &storagep.ResourceId{ 72 SpaceId: user.Id.OpaqueId, 73 OpaqueId: user.Id.OpaqueId, 74 }, 75 Path: ".", 76 } 77 78 infos2Etags = func(infos []*storagep.ResourceInfo) map[string]string { 79 etags := map[string]string{} 80 for _, info := range infos { 81 etags[info.Path] = info.Etag 82 } 83 return etags 84 } 85 infos2Paths = func(infos []*storagep.ResourceInfo) []string { 86 paths := []string{} 87 for _, info := range infos { 88 paths = append(paths, info.Path) 89 } 90 return paths 91 } 92 ) 93 94 BeforeEach(func() { 95 dependencies = []RevadConfig{ 96 { 97 Name: "gateway", 98 Config: "gateway.toml"}, 99 { 100 Name: "users", 101 Config: "userprovider-json.toml"}, 102 { 103 Name: "storage", 104 Config: "storageprovider-ocis.toml"}, 105 { 106 Name: "storage2", 107 Config: "storageprovider-ocis.toml"}, 108 { 109 Name: "permissions", 110 Config: "permissions-ocis-ci.toml"}, 111 } 112 }) 113 114 JustBeforeEach(func() { 115 var err error 116 ctx = context.Background() 117 118 // Add auth token 119 tokenManager, err := jwt.New(map[string]interface{}{"secret": "changemeplease"}) 120 Expect(err).ToNot(HaveOccurred()) 121 scope, err := scope.AddOwnerScope(nil) 122 Expect(err).ToNot(HaveOccurred()) 123 t, err := tokenManager.MintToken(ctx, user, scope) 124 Expect(err).ToNot(HaveOccurred()) 125 ctx = ctxpkg.ContextSetToken(ctx, t) 126 ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) 127 ctx = ctxpkg.ContextSetUser(ctx, user) 128 129 revads, err = startRevads(dependencies, variables) 130 Expect(err).ToNot(HaveOccurred()) 131 Expect(revads["gateway"]).ToNot(BeNil()) 132 serviceClient, err = pool.GetGatewayServiceClient(revads["gateway"].GrpcAddress) 133 Expect(err).ToNot(HaveOccurred()) 134 }) 135 136 AfterEach(func() { 137 for _, r := range revads { 138 Expect(r.Cleanup(CurrentSpecReport().Failed())).To(Succeed()) 139 } 140 }) 141 142 It("creates a home directory", func() { 143 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 144 Expect(err).ToNot(HaveOccurred()) 145 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 146 147 res, err := serviceClient.CreateHome(ctx, &storagep.CreateHomeRequest{}) 148 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 149 Expect(err).ToNot(HaveOccurred()) 150 151 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 152 Expect(err).ToNot(HaveOccurred()) 153 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 154 155 ghRes, err := serviceClient.GetHome(ctx, &storagep.GetHomeRequest{}) 156 Expect(err).ToNot(HaveOccurred()) 157 Expect(ghRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 158 }) 159 160 Context("with a sharded projects directory", func() { 161 var ( 162 shard1Fs storage.FS 163 shard1Space *storagep.StorageSpace 164 shard2Fs storage.FS 165 projectsRef = &storagep.Reference{Path: "/projects"} 166 167 getProjectsEtag = func() string { 168 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: &storagep.Reference{Path: "/"}}) 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 171 Expect(len(listRes.Infos)).To(Equal(1)) 172 return listRes.Infos[0].Etag 173 } 174 ) 175 176 BeforeEach(func() { 177 dependencies = []RevadConfig{ 178 {Name: "gateway", Config: "gateway-sharded.toml"}, 179 {Name: "users", Config: "userprovider-json.toml"}, 180 {Name: "homestorage", Config: "storageprovider-ocis.toml"}, 181 {Name: "storage", Config: "storageprovider-ocis.toml"}, 182 {Name: "storage2", Config: "storageprovider-ocis.toml"}, 183 {Name: "permissions", Config: "permissions-ocis-ci.toml"}, 184 } 185 }) 186 187 JustBeforeEach(func() { 188 var err error 189 shard1Fs, err = ocis.New(map[string]interface{}{ 190 "root": revads["storage"].StorageRoot, 191 "userprovidersvc": revads["users"].GrpcAddress, 192 "permissionssvc": revads["permissions"].GrpcAddress, 193 "treesize_accounting": true, 194 "treetime_accounting": true, 195 }, nil, &zerolog.Logger{}) 196 Expect(err).ToNot(HaveOccurred()) 197 res, err := shard1Fs.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 198 Type: "project", 199 Name: "a - project", 200 Owner: user, 201 }) 202 Expect(err).ToNot(HaveOccurred()) 203 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 204 shard1Space = res.StorageSpace 205 206 ssid, err := storagespace.ParseID(shard1Space.Id.OpaqueId) 207 Expect(err).ToNot(HaveOccurred()) 208 err = helpers.Upload(ctx, 209 shard1Fs, 210 &storagep.Reference{ResourceId: &ssid, Path: "/file.txt"}, 211 []byte("1"), 212 ) 213 Expect(err).ToNot(HaveOccurred()) 214 215 shard2Fs, err = ocis.New(map[string]interface{}{ 216 "root": revads["storage"].StorageRoot, 217 "userprovidersvc": revads["users"].GrpcAddress, 218 "permissionssvc": revads["permissions"].GrpcAddress, 219 "treesize_accounting": true, 220 "treetime_accounting": true, 221 }, nil, &zerolog.Logger{}) 222 Expect(err).ToNot(HaveOccurred()) 223 res, err = shard2Fs.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 224 Type: "project", 225 Name: "z - project", 226 Owner: user, 227 }) 228 Expect(err).ToNot(HaveOccurred()) 229 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 230 }) 231 232 Describe("ListContainer", func() { 233 // Note: The Gateway doesn't merge any lists any more. This needs to be done by the client 234 // TODO: Move the tests to a place where they can actually test something 235 PIt("merges the lists of both shards", func() { 236 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: projectsRef}) 237 Expect(err).ToNot(HaveOccurred()) 238 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 239 240 Expect(infos2Paths(listRes.Infos)).To(ConsistOf([]string{"/projects/a - project", "/projects/z - project"})) 241 }) 242 243 PIt("propagates the etags from both shards", func() { 244 rootEtag := getProjectsEtag() 245 246 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: projectsRef}) 247 Expect(err).ToNot(HaveOccurred()) 248 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 249 250 etags := infos2Etags(listRes.Infos) 251 Expect(etags["/projects/a - project"]).ToNot(BeNil()) 252 Expect(etags["/projects/z - project"]).ToNot(BeNil()) 253 254 By("creating a new file") 255 err = helpers.Upload(ctx, shard1Fs, &storagep.Reference{ResourceId: &storagep.ResourceId{StorageId: shard1Space.Id.OpaqueId}, Path: "/newfile.txt"}, []byte("1234567890")) 256 Expect(err).ToNot(HaveOccurred()) 257 258 time.Sleep(time.Second) // cache must expire 259 listRes, err = serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: projectsRef}) 260 Expect(err).ToNot(HaveOccurred()) 261 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 262 etags2 := infos2Etags(listRes.Infos) 263 Expect(etags2["/projects/a - project"]).ToNot(Equal(etags["/projects/a - project"])) 264 Expect(etags2["/projects/z - project"]).To(Equal(etags["/projects/z - project"])) 265 266 rootEtag2 := getProjectsEtag() 267 Expect(rootEtag2).ToNot(Equal(rootEtag)) 268 269 By("updating an existing file") 270 err = helpers.Upload(ctx, shard1Fs, &storagep.Reference{ResourceId: &storagep.ResourceId{StorageId: shard1Space.Id.OpaqueId}, Path: "/newfile.txt"}, []byte("12345678901")) 271 Expect(err).ToNot(HaveOccurred()) 272 273 time.Sleep(time.Second) // cache must expire 274 listRes, err = serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: projectsRef}) 275 Expect(err).ToNot(HaveOccurred()) 276 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 277 etags3 := infos2Etags(listRes.Infos) 278 Expect(etags3["/projects/a - project"]).ToNot(Equal(etags2["/projects/a - project"])) 279 Expect(etags3["/projects/z - project"]).To(Equal(etags2["/projects/z - project"])) 280 281 rootEtag3 := getProjectsEtag() 282 Expect(rootEtag3).ToNot(Equal(rootEtag2)) 283 284 By("creating a directory") 285 err = shard1Fs.CreateDir(ctx, &storagep.Reference{ResourceId: &storagep.ResourceId{StorageId: shard1Space.Id.OpaqueId}, Path: "/newdirectory"}) 286 Expect(err).ToNot(HaveOccurred()) 287 288 time.Sleep(time.Second) // cache must expire 289 listRes, err = serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: projectsRef}) 290 Expect(err).ToNot(HaveOccurred()) 291 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 292 etags4 := infos2Etags(listRes.Infos) 293 Expect(etags4["/projects/a - project"]).ToNot(Equal(etags3["/projects/a - project"])) 294 Expect(etags4["/projects/z - project"]).To(Equal(etags3["/projects/z - project"])) 295 296 rootEtag4 := getProjectsEtag() 297 Expect(rootEtag4).ToNot(Equal(rootEtag3)) 298 }) 299 300 It("places new spaces in the correct shard", func() { 301 createRes, err := serviceClient.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 302 Owner: user, 303 Type: "project", 304 Name: "o - project", 305 }) 306 Expect(err).ToNot(HaveOccurred()) 307 Expect(createRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 308 space := createRes.StorageSpace 309 310 ref := &storagep.Reference{ 311 ResourceId: space.Root, 312 Path: ".", 313 } 314 315 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: ref}) 316 Expect(err).ToNot(HaveOccurred()) 317 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 318 319 ssid, err := storagespace.ParseID(space.Id.OpaqueId) 320 Expect(err).ToNot(HaveOccurred()) 321 mpk1, err := os.ReadFile(path.Join(revads["storage"].StorageRoot, "/indexes/by-type/project.mpk")) 322 Expect(err).ToNot(HaveOccurred()) 323 Expect(string(mpk1)).ToNot(ContainSubstring(ssid.OpaqueId)) 324 mpk2, err := os.ReadFile(path.Join(revads["storage2"].StorageRoot, "/indexes/by-type/project.mpk")) 325 Expect(err).ToNot(HaveOccurred()) 326 Expect(string(mpk2)).To(ContainSubstring(ssid.OpaqueId)) 327 }) 328 329 PIt("deletes spaces", func() {}) 330 331 It("lists individual project spaces", func() { 332 By("trying to list a non-existent space") 333 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: &storagep.Reference{ 334 ResourceId: &storagep.ResourceId{ 335 StorageId: "does-not-exist", 336 OpaqueId: "neither-supposed-to-exist", 337 }, 338 Path: ".", 339 }}) 340 Expect(err).ToNot(HaveOccurred()) 341 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 342 343 By("listing an existing space") 344 listRes, err = serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: &storagep.Reference{ResourceId: shard1Space.Root, Path: "."}}) 345 Expect(err).ToNot(HaveOccurred()) 346 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 347 Expect(len(listRes.Infos)).To(Equal(1)) 348 paths := []string{} 349 for _, i := range listRes.Infos { 350 paths = append(paths, i.Path) 351 } 352 Expect(paths).To(ConsistOf([]string{"file.txt"})) 353 }) 354 355 }) 356 }) 357 358 Context("with a basic user storage", func() { 359 var ( 360 fs storage.FS 361 embeddedFs storage.FS 362 homeSpace *storagep.StorageSpace 363 embeddedSpace *storagep.StorageSpace 364 embeddedRef *storagep.Reference 365 ) 366 367 BeforeEach(func() { 368 dependencies = []RevadConfig{ 369 {Name: "gateway", Config: "gateway.toml"}, 370 {Name: "users", Config: "userprovider-json.toml"}, 371 {Name: "storage", Config: "storageprovider-ocis.toml"}, 372 {Name: "storage2", Config: "storageprovider-ocis.toml"}, 373 {Name: "permissions", Config: "permissions-ocis-ci.toml"}, 374 } 375 }) 376 377 JustBeforeEach(func() { 378 var err error 379 fs, err = ocis.New(map[string]interface{}{ 380 "root": revads["storage"].StorageRoot, 381 "permissionssvc": revads["permissions"].GrpcAddress, 382 "treesize_accounting": true, 383 "treetime_accounting": true, 384 }, nil, &zerolog.Logger{}) 385 Expect(err).ToNot(HaveOccurred()) 386 387 r, err := serviceClient.CreateHome(ctx, &storagep.CreateHomeRequest{}) 388 Expect(err).ToNot(HaveOccurred()) 389 Expect(r.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 390 391 spaces, err := fs.ListStorageSpaces(ctx, []*storagep.ListStorageSpacesRequest_Filter{}, false) 392 Expect(err).ToNot(HaveOccurred()) 393 homeSpace = spaces[0] 394 ssid, err := storagespace.ParseID(homeSpace.Id.OpaqueId) 395 Expect(err).ToNot(HaveOccurred()) 396 err = helpers.Upload(ctx, 397 fs, 398 &storagep.Reference{ResourceId: &ssid, Path: "/file.txt"}, 399 []byte("1"), 400 ) 401 Expect(err).ToNot(HaveOccurred()) 402 403 embeddedFs, err = ocis.New(map[string]interface{}{ 404 "root": revads["storage2"].StorageRoot, 405 "userprovidersvc": revads["users"].GrpcAddress, 406 "permissionssvc": revads["permissions"].GrpcAddress, 407 "treesize_accounting": true, 408 "treetime_accounting": true, 409 }, nil, &zerolog.Logger{}) 410 Expect(err).ToNot(HaveOccurred()) 411 res, err := serviceClient.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 412 Type: "project", 413 Name: "embedded project", 414 Owner: user, 415 }) 416 Expect(err).ToNot(HaveOccurred()) 417 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 418 embeddedSpace = res.StorageSpace 419 essid, err := storagespace.ParseID(embeddedSpace.Id.OpaqueId) 420 Expect(err).ToNot(HaveOccurred()) 421 embeddedRef = &storagep.Reference{ 422 ResourceId: &essid, 423 Path: ".", // path.Join(homeRef.Path, "Projects", embeddedSpace.Id.OpaqueId), 424 } 425 err = helpers.Upload(ctx, 426 embeddedFs, 427 &storagep.Reference{ResourceId: &essid, Path: "/embedded.txt"}, 428 []byte("22"), 429 ) 430 Expect(err).ToNot(HaveOccurred()) 431 }) 432 433 Describe("ListContainer", func() { 434 It("lists the root", func() { 435 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: homeRef}) 436 Expect(err).ToNot(HaveOccurred()) 437 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 438 Expect(len(listRes.Infos)).To(Equal(1)) 439 440 var fileInfo *storagep.ResourceInfo 441 // var embeddedInfo *storagep.ResourceInfo 442 for _, i := range listRes.Infos { 443 if i.Path == "file.txt" { 444 fileInfo = i 445 } // else if i.Path == "Projects" { 446 // embeddedInfo = i 447 // } 448 449 } 450 Expect(fileInfo).ToNot(BeNil()) 451 Expect(fileInfo.Owner.OpaqueId).To(Equal(user.Id.OpaqueId)) 452 Expect(fileInfo.Path).To(Equal("file.txt")) 453 Expect(fileInfo.Size).To(Equal(uint64(1))) 454 455 // Expect(embeddedInfo).ToNot(BeNil()) 456 // Expect(embeddedInfo.Owner.OpaqueId).To(Equal(user.Id.OpaqueId)) 457 // Expect(embeddedInfo.Path).To(Equal("Projects")) 458 // Expect(embeddedInfo.Size).To(Equal(uint64(2))) 459 }) 460 461 PIt("lists the embedded project space", func() { 462 listRes, err := serviceClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: embeddedRef}) 463 Expect(err).ToNot(HaveOccurred()) 464 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 465 Expect(len(listRes.Infos)).To(Equal(2)) 466 467 var embeddedInfo *storagep.ResourceInfo 468 for _, i := range listRes.Infos { 469 if i.Path == path.Join(embeddedRef.Path, "embedded.txt") { 470 embeddedInfo = i 471 } 472 473 } 474 Expect(embeddedInfo).ToNot(BeNil()) 475 Expect(embeddedInfo.Owner.OpaqueId).To(Equal(user.Id.OpaqueId)) 476 Expect(embeddedInfo.Path).To(Equal(path.Join(embeddedRef.Path, "embedded.txt"))) 477 Expect(embeddedInfo.Size).To(Equal(uint64(2))) 478 }) 479 }) 480 481 Describe("Stat", func() { 482 It("stats the root", func() { 483 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 484 Expect(err).ToNot(HaveOccurred()) 485 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 486 487 info := statRes.Info 488 Expect(info.Type).To(Equal(storagep.ResourceType_RESOURCE_TYPE_CONTAINER)) 489 Expect(utils.ResourceIDEqual(info.Id, homeRef.ResourceId)).To(BeTrue()) 490 Expect(info.Path).To(Equal(".")) // path of a root node of a space is always "." 491 Expect(info.Owner.OpaqueId).To(Equal(user.Id.OpaqueId)) 492 493 // TODO: size aggregating is done by the client now - so no chance testing that here 494 // Expect(info.Size).To(Equal(uint64(3))) // home: 1, embedded: 2 495 }) 496 497 It("stats the root of embedded space", func() { 498 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: embeddedRef}) 499 Expect(err).ToNot(HaveOccurred()) 500 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 501 502 info := statRes.Info 503 Expect(info.Type).To(Equal(storagep.ResourceType_RESOURCE_TYPE_CONTAINER)) 504 Expect(utils.ResourceIDEqual(info.Id, embeddedRef.ResourceId)).To(BeTrue()) 505 Expect(info.Path).To(Equal(".")) // path of a root node of a space is always "." 506 Expect(info.Size).To(Equal(uint64(2))) 507 }) 508 509 PIt("propagates Sizes from within the root space", func() { 510 // TODO: this cannot work atm as the propagation is not done by the gateway anymore 511 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 512 Expect(err).ToNot(HaveOccurred()) 513 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 514 Expect(statRes.Info.Size).To(Equal(uint64(3))) 515 516 By("Uploading a new file") 517 rid, err := storagespace.ParseID(homeSpace.Id.OpaqueId) 518 Expect(err).ToNot(HaveOccurred()) 519 err = helpers.Upload(ctx, fs, &storagep.Reference{ResourceId: &rid, Path: "/newfile.txt"}, []byte("1234567890")) 520 Expect(err).ToNot(HaveOccurred()) 521 522 time.Sleep(time.Second) // cache must expire 523 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 524 Expect(err).ToNot(HaveOccurred()) 525 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 526 Expect(statRes.Info.Size).To(Equal(uint64(13))) 527 528 By("Uploading a new file into a subdir") 529 err = fs.CreateDir(ctx, &storagep.Reference{ResourceId: &rid, Path: "/newdir"}) 530 Expect(err).ToNot(HaveOccurred()) 531 err = helpers.Upload(ctx, fs, &storagep.Reference{ResourceId: &rid, Path: "/newdir/newfile.txt"}, []byte("1234567890")) 532 Expect(err).ToNot(HaveOccurred()) 533 534 time.Sleep(time.Second) // cache must expire 535 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 536 Expect(err).ToNot(HaveOccurred()) 537 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 538 Expect(statRes.Info.Size).To(Equal(uint64(23))) 539 540 By("Updating an existing file") 541 err = helpers.Upload(ctx, fs, &storagep.Reference{ResourceId: &rid, Path: "/newdir/newfile.txt"}, []byte("12345678901234567890")) 542 Expect(err).ToNot(HaveOccurred()) 543 544 time.Sleep(time.Second) // cache must expire 545 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 546 Expect(err).ToNot(HaveOccurred()) 547 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 548 Expect(statRes.Info.Size).To(Equal(uint64(33))) 549 }) 550 551 PIt("propagates Sizes from within the embedded space", func() { 552 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 553 Expect(err).ToNot(HaveOccurred()) 554 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 555 Expect(statRes.Info.Size).To(Equal(uint64(3))) 556 557 By("Uploading a new file") 558 rid, err := storagespace.ParseID(embeddedSpace.Id.OpaqueId) 559 Expect(err).ToNot(HaveOccurred()) 560 err = helpers.Upload(ctx, embeddedFs, &storagep.Reference{ResourceId: &rid, Path: "/newfile.txt"}, []byte("1234567890")) 561 Expect(err).ToNot(HaveOccurred()) 562 563 time.Sleep(time.Second) // cache must expire 564 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 565 Expect(err).ToNot(HaveOccurred()) 566 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 567 Expect(statRes.Info.Size).To(Equal(uint64(13))) 568 569 By("Uploading a new file into a subdir") 570 err = embeddedFs.CreateDir(ctx, &storagep.Reference{ResourceId: &rid, Path: "/newdir"}) 571 Expect(err).ToNot(HaveOccurred()) 572 err = helpers.Upload(ctx, embeddedFs, &storagep.Reference{ResourceId: &rid, Path: "/newdir/newfile.txt"}, []byte("1234567890")) 573 Expect(err).ToNot(HaveOccurred()) 574 575 time.Sleep(time.Second) // cache must expire 576 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 577 Expect(err).ToNot(HaveOccurred()) 578 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 579 Expect(statRes.Info.Size).To(Equal(uint64(23))) 580 581 By("Updating an existing file") 582 err = helpers.Upload(ctx, embeddedFs, &storagep.Reference{ResourceId: &rid, Path: "/newdir/newfile.txt"}, []byte("12345678901234567890")) 583 Expect(err).ToNot(HaveOccurred()) 584 585 time.Sleep(time.Second) // cache must expire 586 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 587 Expect(err).ToNot(HaveOccurred()) 588 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 589 Expect(statRes.Info.Size).To(Equal(uint64(33))) 590 }) 591 592 It("propagates Etags from within the root space", func() { 593 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 594 Expect(err).ToNot(HaveOccurred()) 595 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 596 etag := statRes.Info.Etag 597 ssid, err := storagespace.ParseID(homeSpace.Id.OpaqueId) 598 Expect(err).ToNot(HaveOccurred()) 599 By("Uploading a new file") 600 err = helpers.Upload(ctx, fs, &storagep.Reference{ResourceId: &ssid, Path: "/newfile.txt"}, []byte("1")) 601 Expect(err).ToNot(HaveOccurred()) 602 603 time.Sleep(time.Second) // cache must expire 604 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 605 Expect(err).ToNot(HaveOccurred()) 606 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 607 newEtag := statRes.Info.Etag 608 609 Expect(newEtag).ToNot(Equal(etag)) 610 611 By("Creating a new dir") 612 err = fs.CreateDir(ctx, &storagep.Reference{ResourceId: &ssid, Path: "/newdir"}) 613 Expect(err).ToNot(HaveOccurred()) 614 615 time.Sleep(time.Second) // cache must expire 616 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 617 Expect(err).ToNot(HaveOccurred()) 618 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 619 newEtag2 := statRes.Info.Etag 620 621 Expect(newEtag2).ToNot(Equal(newEtag)) 622 623 By("Updating an existing file") 624 err = helpers.Upload(ctx, fs, &storagep.Reference{ResourceId: &ssid, Path: "/file.txt"}, []byte("2")) 625 Expect(err).ToNot(HaveOccurred()) 626 627 time.Sleep(time.Second) // cache must expire 628 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 629 Expect(err).ToNot(HaveOccurred()) 630 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 631 newEtag3 := statRes.Info.Etag 632 633 Expect(newEtag3).ToNot(Equal(newEtag2)) 634 }) 635 636 PIt("propagates Etags from within the embedded space", func() { 637 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 638 Expect(err).ToNot(HaveOccurred()) 639 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 640 etag := statRes.Info.Etag 641 essid, err := storagespace.ParseID(embeddedSpace.Id.OpaqueId) 642 Expect(err).ToNot(HaveOccurred()) 643 By("Uploading a new file") 644 err = helpers.Upload(ctx, embeddedFs, &storagep.Reference{ResourceId: &essid, Path: "/newfile.txt"}, []byte("1")) 645 Expect(err).ToNot(HaveOccurred()) 646 647 time.Sleep(time.Second) // cache must expire 648 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 649 Expect(err).ToNot(HaveOccurred()) 650 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 651 newEtag := statRes.Info.Etag 652 653 Expect(newEtag).ToNot(Equal(etag)) 654 655 By("Creating a new dir") 656 err = embeddedFs.CreateDir(ctx, &storagep.Reference{ResourceId: &essid, Path: "/newdir"}) 657 Expect(err).ToNot(HaveOccurred()) 658 659 time.Sleep(time.Second) // cache must expire 660 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 661 Expect(err).ToNot(HaveOccurred()) 662 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 663 newEtag2 := statRes.Info.Etag 664 665 Expect(newEtag2).ToNot(Equal(newEtag)) 666 667 By("Updating an existing file") 668 err = helpers.Upload(ctx, embeddedFs, &storagep.Reference{ResourceId: &essid, Path: "/newfile.txt"}, []byte("1")) 669 Expect(err).ToNot(HaveOccurred()) 670 671 time.Sleep(time.Second) // cache must expire 672 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 673 Expect(err).ToNot(HaveOccurred()) 674 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 675 newEtag3 := statRes.Info.Etag 676 677 Expect(newEtag3).ToNot(Equal(newEtag2)) 678 }) 679 }) 680 681 Describe("Move", func() { 682 It("moves a directory", func() { 683 hssid, err := storagespace.ParseID(homeSpace.Id.OpaqueId) 684 Expect(err).ToNot(HaveOccurred()) 685 sourceRef := &storagep.Reference{ResourceId: &hssid, Path: "./source"} 686 targetRef := &storagep.Reference{ResourceId: &hssid, Path: "./destination"} 687 dstRef := &storagep.Reference{ResourceId: &hssid, Path: "./destination/source"} 688 689 err = fs.CreateDir(ctx, sourceRef) 690 Expect(err).ToNot(HaveOccurred()) 691 err = fs.CreateDir(ctx, targetRef) 692 Expect(err).ToNot(HaveOccurred()) 693 694 mvRes, err := serviceClient.Move(ctx, &storagep.MoveRequest{Source: sourceRef, Destination: dstRef}) 695 Expect(err).ToNot(HaveOccurred()) 696 Expect(mvRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 697 698 statRes, err := serviceClient.Stat(ctx, &storagep.StatRequest{Ref: sourceRef}) 699 Expect(err).ToNot(HaveOccurred()) 700 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 701 statRes, err = serviceClient.Stat(ctx, &storagep.StatRequest{Ref: dstRef}) 702 Expect(err).ToNot(HaveOccurred()) 703 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 704 }) 705 }) 706 }) 707 })