From f173e16c02f11e0c3280c695591eee1038f25a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20J=C3=BCrgensmeyer?= Date: Tue, 26 Nov 2024 09:27:40 +0100 Subject: [PATCH] rgw/admin: support new-bucket-name for LinkBucket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Simon Jürgensmeyer --- rgw/admin/link.go | 22 +++++++++++------ rgw/admin/link_test.go | 55 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/rgw/admin/link.go b/rgw/admin/link.go index 72378313f..ed865e075 100644 --- a/rgw/admin/link.go +++ b/rgw/admin/link.go @@ -5,16 +5,15 @@ import ( "net/http" ) -// BucketLinkInput the bucket link/unlink input parameters -type BucketLinkInput struct { - Bucket string `url:"bucket" json:"bucket"` - BucketID string `url:"bucket-id" json:"bucket_id"` - UID string `url:"uid" json:"uid"` +// BucketUnlinkInput the bucket unlink input parameters +type BucketUnlinkInput struct { + Bucket string `url:"bucket" json:"bucket"` + UID string `url:"uid" json:"uid"` } // UnlinkBucket unlink a bucket from a specified user // Primarily useful for changing bucket ownership. -func (api *API) UnlinkBucket(ctx context.Context, link BucketLinkInput) error { +func (api *API) UnlinkBucket(ctx context.Context, link BucketUnlinkInput) error { if link.UID == "" { return errMissingUserID } @@ -25,6 +24,14 @@ func (api *API) UnlinkBucket(ctx context.Context, link BucketLinkInput) error { return err } +// BucketLinkInput the bucket link input parameters +type BucketLinkInput struct { + Bucket string `url:"bucket" json:"bucket"` + BucketID string `url:"bucket-id" json:"bucket_id"` + UID string `url:"uid" json:"uid"` + NewBucketName string `url:"new-bucket-name" json:"new_bucket_name"` // Optional; use to rename a bucket. While the tenant-id can be specified, this is not necessary in normal operation. +} + // LinkBucket will link a bucket to a specified user // unlinking the bucket from any previous user func (api *API) LinkBucket(ctx context.Context, link BucketLinkInput) error { @@ -34,7 +41,6 @@ func (api *API) LinkBucket(ctx context.Context, link BucketLinkInput) error { if link.Bucket == "" { return errMissingBucket } - // valid parameters not supported by go-ceph: new-bucket-name - _, err := api.call(ctx, http.MethodPut, "/bucket", valueToURLParams(link, []string{"uid", "bucket-id", "bucket"})) + _, err := api.call(ctx, http.MethodPut, "/bucket", valueToURLParams(link, []string{"uid", "bucket-id", "bucket", "new-bucket-name"})) return err } diff --git a/rgw/admin/link_test.go b/rgw/admin/link_test.go index 506ac817c..4a6e5c776 100644 --- a/rgw/admin/link_test.go +++ b/rgw/admin/link_test.go @@ -55,7 +55,7 @@ func (suite *RadosGWTestSuite) TestLink() { bucket, err := co.GetBucketInfo(context.Background(), Bucket{Bucket: suite.bucketTestName}) assert.NoError(t, err) - err = co.UnlinkBucket(context.Background(), BucketLinkInput{ + err = co.UnlinkBucket(context.Background(), BucketUnlinkInput{ Bucket: suite.bucketTestName, UID: bucket.Owner, }) @@ -76,4 +76,57 @@ func (suite *RadosGWTestSuite) TestLink() { err := co.RemoveUser(context.Background(), User{ID: "test-user2"}) assert.NoError(suite.T(), err) }) + +} + +func (suite *RadosGWTestSuite) TestLinkRename() { + suite.SetupConnection() + co, err := New(suite.endpoint, suite.accessKey, suite.secretKey, newDebugHTTPClient(http.DefaultClient)) + assert.NoError(suite.T(), err) + + const ( + userName = "test-user-bucket-rename" + initialBucketName = "initial-name" + renamedBucketName = "renamed-name" + ) + + suite.T().Run("create test user for bucket rename", func(_ *testing.T) { + user, err := co.CreateUser(context.Background(), User{ID: userName, DisplayName: userName, Email: "test-user-bucket-rename@example.com"}) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), userName, user.ID) + assert.Zero(suite.T(), len(user.Caps)) + }) + + suite.T().Run("create test bucket for rename", func(t *testing.T) { + s3, err := newS3Agent(suite.accessKey, suite.secretKey, suite.endpoint, true) + assert.NoError(t, err) + + err = s3.createBucket(initialBucketName) + assert.NoError(t, err) + }) + + suite.T().Run("rename bucket", func(t *testing.T) { + err = co.LinkBucket(context.Background(), BucketLinkInput{ + UID: userName, + Bucket: initialBucketName, + NewBucketName: renamedBucketName, + }) + assert.NoError(suite.T(), err) + + _, err = co.GetBucketInfo(context.Background(), Bucket{Bucket: initialBucketName}) + assert.ErrorIs(t, err, ErrNoSuchBucket) + + _, err = co.GetBucketInfo(context.Background(), Bucket{Bucket: renamedBucketName}) + assert.NoError(t, err) + }) + + suite.T().Run("remove bucket", func(_ *testing.T) { + err := co.RemoveBucket(context.Background(), Bucket{Bucket: renamedBucketName}) + assert.NoError(suite.T(), err) + }) + + suite.T().Run("delete test user for bucket rename", func(_ *testing.T) { + err := co.RemoveUser(context.Background(), User{ID: userName}) + assert.NoError(suite.T(), err) + }) }