Repository: ceph/go-ceph
Pull request #546 (2021-08-05 08:48:47)

rgw/admin: include stat information to User Struct
The stat information gives idea about current storage consumption.
Include that info to the user struct

[Updated} also added url for `user cap` in the api request

Signed-off-by: Jiffin Tony Thottan <thottanjiffin@gmail.com>


<!--
Thank you for opening a pull request. Please provide:

- A clear summary of your changes

- Descriptive and succinct commit messages with the format:
  """
  [topic]: [short description]

  [Longer description]

  Signed-off-by: [Your Name] <[your email]>
  """

  Topic will generally be the go ceph package dir you are working in.

- Ensure checklist items listed below are accounted for
-->

## Checklist
- [ ] Added tests for features and functional changes
- [ ] Public functions and types are documented
- [ ] Standard formatting is applied to Go code


thotz: > Unit tests?

Done
thotz: Please review @ansiwen @phlogistonjohn. This is needed for https://github.com/openshift/ocs-operator/pull/1268
phlogistonjohn: There's no tests for the new UserCaps field. Was this intentional or just an oversight?
Ideally, if this field isn't directly related to the UserStat stuff it should be in a 2nd patch, but I won't enforce that this time .
phlogistonjohn: Hi @thotz it looks like your new test is still failing. Do you think it would be simpler to revert this PR back to the earlier state so that we can review and merge the User struct feature and work on the User Caps feature + test in a new PR?  Just a suggestion but it might speed things up overall....
obnoxxx: > Hi @thotz it looks like your new test is still failing. Do you think it would be simpler to revert this PR back to the earlier state so that we can review and merge the User struct feature and work on the User Caps feature + test in a new PR? Just a suggestion but it might speed things up overall....

I agree that the caps addition should be a separate commit and PR.

As a general rule of thumb, if a commit message (or PR description) reads something like `do this AND this` then the knee jerk reaction should probably be to split it up. 😄 
thotz: > Suggest to split the caps part out into a separate commit and PR.
> 
> The caps test is failing - accessing first element in array of length 0.

Yaa I think it is better to separate them as @phlogistonjohn and @obnoxxx suggested, debug other issue seperately.

Patch:
diff --git a/rgw/admin/user.go b/rgw/admin/user.go
index 693f194..bef91e9 100644
--- a/rgw/admin/user.go
+++ b/rgw/admin/user.go
@@ -31,6 +31,9 @@ type User struct {
 	Tenant              string        `url:"tenant"`
 	GenerateKey         *bool         `url:"generate-key"`
 	PurgeData           *int          `url:"purge-data"`
+	GenerateStat        *bool         `url:"stats"`
+	Stat                UserStat      `json:"stats"`
+	UserCaps            string        `url:"user-caps"`
 }
 
 // UserCapSpec represents a user capability which gives access to certain ressources
@@ -46,6 +49,13 @@ type UserKeySpec struct {
 	SecretKey string `json:"secret_key" url:"secret-key"`
 }
 
+// UserStat contains information about storage consumption by the ceph user
+type UserStat struct {
+	Size        *uint64 `json:"size"`
+	SizeRounded *uint64 `json:"size_rounded"`
+	NumObjects  *uint64 `json:"num_objects"`
+}
+
 // GetUser retrieves a given object store user
 func (api *API) GetUser(ctx context.Context, user User) (User, error) {
 	if user.ID == "" {


Test patch:
diff --git a/rgw/admin/user_test.go b/rgw/admin/user_test.go
index 8e53e02..6bef049 100644
--- a/rgw/admin/user_test.go
+++ b/rgw/admin/user_test.go
@@ -95,7 +95,8 @@ func (suite *RadosGWTestSuite) TestUser() {
 	})
 
 	suite.T().Run("user creation success", func(t *testing.T) {
-		user, err := co.CreateUser(context.Background(), User{ID: "leseb", DisplayName: "This is leseb", Email: "leseb@example.com"})
+		usercaps := "users=read"
+		user, err := co.CreateUser(context.Background(), User{ID: "leseb", DisplayName: "This is leseb", Email: "leseb@example.com", UserCaps: usercaps})
 		assert.NoError(suite.T(), err)
 		assert.Equal(suite.T(), "leseb@example.com", user.Email)
 	})
@@ -104,6 +105,8 @@ func (suite *RadosGWTestSuite) TestUser() {
 		user, err := co.GetUser(context.Background(), User{ID: "leseb"})
 		assert.NoError(suite.T(), err)
 		assert.Equal(suite.T(), "leseb@example.com", user.Email)
+		assert.Equal(suite.T(), "users", user.Caps[0].Type)
+		assert.Equal(suite.T(), "read", user.Caps[0].Perm)
 	})
 
 	suite.T().Run("modify user email", func(t *testing.T) {
@@ -145,6 +148,13 @@ func (suite *RadosGWTestSuite) TestUser() {
 		assert.Equal(suite.T(), int64(100), *q.MaxObjects)
 	})
 
+	suite.T().Run("get user stat", func(t *testing.T) {
+		statEnable := true
+		user, err := co.GetUser(context.Background(), User{ID: "leseb", GenerateStat: &statEnable})
+		assert.NoError(suite.T(), err)
+		assert.NotNil(suite.T(), user.Stat.Size)
+	})
+
 	suite.T().Run("remove user", func(t *testing.T) {
 		err = co.RemoveUser(context.Background(), User{ID: "leseb"})
 		assert.NoError(suite.T(), err)