Skip to content

Commit

Permalink
ceph: add support for update() from lib-bucket-provisioner
Browse files Browse the repository at this point in the history
Recently lib-bucket-provisioner add support for update() API.
Include that on the obc implementation since it can be used to
update quota for OBC.

Fixes: rook#7146

Signed-off-by: Jiffin Tony Thottan <thottanjiffin@gmail.com>
  • Loading branch information
thotz committed Aug 12, 2021
1 parent 3d68f7e commit 0b8ed1d
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 11 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/google/uuid v1.1.2
github.com/hashicorp/vault/api v1.0.5-0.20200902155336-f9d5ce5a171a
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.1.0
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20210311161930-4bea5edaff58
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20210726163943-56c73fc7c20b
github.com/libopenstorage/secrets v0.0.0-20210709082113-dde442ea20ec
github.com/openshift/cluster-api v0.0.0-20191129101638-b09907ac6668
github.com/openshift/machine-api-operator v0.2.1-0.20190903202259-474e14e4965a
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -719,8 +719,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20210311161930-4bea5edaff58 h1:O9m6tfyhjr3F3yKGsgGMp1+seFyTRovmGMmbcNp6GSo=
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20210311161930-4bea5edaff58/go.mod h1:XpQ9HGG9uF5aJCBP+s6w5kSiyTIVSqCV8+XAE4qms5E=
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20210726163943-56c73fc7c20b h1:0gTJAZ+tTj8mAOtJxMGJi0fsNgfVr3w3DQo3MNQpu+M=
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20210726163943-56c73fc7c20b/go.mod h1:XpQ9HGG9uF5aJCBP+s6w5kSiyTIVSqCV8+XAE4qms5E=
github.com/kubernetes-csi/csi-lib-utils v0.9.1 h1:sGq6ifVujfMSkfTsMZip44Ttv8SDXvsBlFk9GdYl/b8=
github.com/kubernetes-csi/csi-lib-utils v0.9.1/go.mod h1:8E2jVUX9j3QgspwHXa6LwyN7IHQDjW9jX3kwoWnSC+M=
github.com/kubernetes-csi/external-snapshotter/client/v4 v4.0.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys=
Expand Down
70 changes: 68 additions & 2 deletions pkg/operator/ceph/object/bucket/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,8 @@ func (p *Provisioner) deleteOBCResourceLogError(bucketname string) {
// Check for additional options mentioned in OBC and set them accordingly
func (p Provisioner) setAdditionalSettings(options *apibkt.BucketOptions) error {
quotaEnabled := true
maxObjects := MaxObjectQuota(options)
maxSize := MaxSizeQuota(options)
maxObjects := MaxObjectQuota(options.ObjectBucketClaim.Spec.AdditionalConfig)
maxSize := MaxSizeQuota(options.ObjectBucketClaim.Spec.AdditionalConfig)
if maxObjects == "" && maxSize == "" {
return nil
}
Expand Down Expand Up @@ -665,3 +665,69 @@ func (p *Provisioner) setAdminOpsAPIClient() error {

return nil
}
func (p Provisioner) updateAdditionalSettings(ob *bktv1alpha1.ObjectBucket) error {
var maxObjectsInt64 int64
var maxSizeInt64 int64
var err error
var quotaEnabled bool
maxObjects := MaxObjectQuota(ob.Spec.Endpoint.AdditionalConfigData)
maxSize := MaxSizeQuota(ob.Spec.Endpoint.AdditionalConfigData)
if maxObjects != "" {
maxObjectsInt, err := strconv.Atoi(maxObjects)
if err != nil {
return errors.Wrap(err, "failed to convert maxObjects to integer")
}
maxObjectsInt64 = int64(maxObjectsInt)
}
if maxSize != "" {
maxSizeInt64, err = maxSizeToInt64(maxSize)
if err != nil {
return errors.Wrapf(err, "failed to parse maxSize quota for user %q", p.cephUserName)
}
}
objectUser, err := p.adminOpsClient.GetUser(context.TODO(), admin.User{ID: ob.Spec.Connection.AdditionalState[cephUser]})
if err != nil {
return errors.Wrapf(err, "failed to fetch user %q", p.cephUserName)
}
if *objectUser.UserQuota.Enabled &&
(maxObjects == "" || maxObjectsInt64 < 0) &&
(maxSize == "" || maxSizeInt64 < 0) {
quotaEnabled = false
err = p.adminOpsClient.SetUserQuota(context.TODO(), admin.QuotaSpec{UID: p.cephUserName, Enabled: &quotaEnabled})
if err != nil {
return errors.Wrapf(err, "failed to disable quota to user %q", p.cephUserName)
}
return nil
}

quotaEnabled = true
quotaSpec := admin.QuotaSpec{UID: p.cephUserName, Enabled: &quotaEnabled}

//MaxObject is modified
if maxObjects != "" && (maxObjectsInt64 != *objectUser.UserQuota.MaxObjects) {
quotaSpec.MaxObjects = &maxObjectsInt64
}

//MaxSize is modified
if maxSize != "" && (maxSizeInt64 != *objectUser.UserQuota.MaxSize) {
quotaSpec.MaxSize = &maxSizeInt64
}
err = p.adminOpsClient.SetUserQuota(context.TODO(), quotaSpec)
if err != nil {
return errors.Wrapf(err, "failed to update quota to user %q", p.cephUserName)
}

return nil
}

// Update is sent when only there is modification to AdditionalConfig field in OBC
func (p Provisioner) Update(ob *bktv1alpha1.ObjectBucket) error {
logger.Debugf("Update event for OB: %+v", ob)

err := p.initializeDeleteOrRevoke(ob)
if err != nil {
return err
}

return p.updateAdditionalSettings(ob)
}
9 changes: 4 additions & 5 deletions pkg/operator/ceph/object/bucket/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/coreos/pkg/capnslog"
bktv1alpha1 "github.com/kube-object-storage/lib-bucket-provisioner/pkg/apis/objectbucket.io/v1alpha1"
"github.com/kube-object-storage/lib-bucket-provisioner/pkg/provisioner"
apibkt "github.com/kube-object-storage/lib-bucket-provisioner/pkg/provisioner/api"
"github.com/pkg/errors"
storagev1 "k8s.io/api/storage/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -117,10 +116,10 @@ func randomString(n int) string {
return string(b)
}

func MaxObjectQuota(options *apibkt.BucketOptions) string {
return options.ObjectBucketClaim.Spec.AdditionalConfig["maxObjects"]
func MaxObjectQuota(AdditionalConfig map[string]string) string {
return AdditionalConfig["maxObjects"]
}

func MaxSizeQuota(options *apibkt.BucketOptions) string {
return options.ObjectBucketClaim.Spec.AdditionalConfig["maxSize"]
func MaxSizeQuota(AdditionalConfig map[string]string) string {
return AdditionalConfig["maxSize"]
}
11 changes: 11 additions & 0 deletions tests/framework/clients/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ func (b *BucketOperation) DeleteObc(obcName string, storageClassName string, buc
return b.k8sh.ResourceOperation("delete", b.manifests.GetOBC(obcName, storageClassName, bucketName, maxObject, createBucket))
}

func (b *BucketOperation) UpdateObc(obcName string, storageClassName string, bucketName string, maxObject string, createBucket bool) error {
return b.k8sh.ResourceOperation("apply", b.manifests.GetOBC(obcName, storageClassName, bucketName, maxObject, createBucket))
}

// CheckOBC, returns true if the obc, secret and configmap are all in the "check" state,
// and returns false if any of these resources are not in the "check" state.
// Check state values:
Expand Down Expand Up @@ -123,3 +127,10 @@ func (b *BucketOperation) GetSecretKey(obcName string) (string, error) {
return string(decode), nil

}

// Checks whether MaxObject is updated for ob
func (b *BucketOperation) CheckOBMaxObject(obcName, maxobject string) bool {
obName, _ := b.k8sh.GetResource("obc", obcName, "--output", "jsonpath={.spec.objectBucketName}")
fetchMaxObject, _ := b.k8sh.GetResource("ob", obName, "--output", "jsonpath={.spec.endpoint.additionalConfig.maxObjects}")
return maxobject == fetchMaxObject
}
18 changes: 17 additions & 1 deletion tests/integration/ceph_base_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ var (
ObjectKey1 = "rookObj1"
ObjectKey2 = "rookObj2"
ObjectKey3 = "rookObj3"
ObjectKey4 = "rookObj4"
contentType = "plain/text"
obcName = "smoke-delete-bucket"
region = "us-east-1"
maxObject = "2"
newMaxObject = "3"
bucketStorageClassName = "rook-smoke-delete-bucket"
)

Expand Down Expand Up @@ -279,12 +281,26 @@ func testObjectStoreOperations(s suite.Suite, helper *clients.TestClient, k8sh *
_, poErr = s3client.PutObjectInBucket(bucketname, ObjBody, ObjectKey3, contentType)
assert.Error(s.T(), poErr)
})

t.Run("test update quota on OBC bucket", func(t *testing.T) {
poErr := helper.BucketClient.UpdateObc(obcName, bucketStorageClassName, bucketname, newMaxObject, true)
assert.Nil(s.T(), poErr)
updated := utils.Retry(5, 2*time.Second, "OBC is created", func() bool {
return helper.BucketClient.CheckOBMaxObject(obcName, newMaxObject)
})
assert.True(s.T(), updated)
logger.Infof("Testing the updated object limit")
_, poErr = s3client.PutObjectInBucket(bucketname, ObjBody, ObjectKey3, contentType)
assert.Nil(s.T(), poErr)
_, poErr = s3client.PutObjectInBucket(bucketname, ObjBody, ObjectKey4, contentType)
assert.Error(s.T(), poErr)
})
t.Run("delete objects on OBC bucket", func(t *testing.T) {
_, delobjErr := s3client.DeleteObjectInBucket(bucketname, ObjectKey1)
assert.Nil(s.T(), delobjErr)
_, delobjErr = s3client.DeleteObjectInBucket(bucketname, ObjectKey2)
assert.Nil(s.T(), delobjErr)
_, delobjErr = s3client.DeleteObjectInBucket(bucketname, ObjectKey3)
assert.Nil(s.T(), delobjErr)
logger.Info("Objects deleted on bucket successfully")
})
})
Expand Down

0 comments on commit 0b8ed1d

Please sign in to comment.