forked from TrueCloudLab/frostfs-s3-gw
[#195] Support enabling object locking for bucket
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
40b6365afb
commit
e98c663bd6
5 changed files with 41 additions and 17 deletions
|
@ -25,6 +25,7 @@ type (
|
|||
Created time.Time
|
||||
BasicACL uint32
|
||||
LocationConstraint string
|
||||
ObjectLockEnabled bool
|
||||
}
|
||||
|
||||
// ObjectInfo holds S3 object data.
|
||||
|
|
|
@ -565,18 +565,36 @@ func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||
p.Policy = h.cfg.DefaultPolicy
|
||||
}
|
||||
|
||||
p.ObjectLockEnabled = isLockEnabled(r.Header)
|
||||
|
||||
cid, err := h.obj.CreateBucket(r.Context(), &p)
|
||||
if err != nil {
|
||||
h.logAndSendError(w, "could not create bucket", reqInfo, err)
|
||||
return
|
||||
}
|
||||
|
||||
if p.ObjectLockEnabled {
|
||||
vp := &layer.PutVersioningParams{
|
||||
Bucket: reqInfo.BucketName,
|
||||
Settings: &layer.BucketSettings{VersioningEnabled: true},
|
||||
}
|
||||
if _, err = h.obj.PutBucketVersioning(r.Context(), vp); err != nil {
|
||||
h.log.Error("couldn't enable bucket versioning", zap.Stringer("container_id", cid), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
h.log.Info("bucket is created",
|
||||
zap.String("container_id", cid.String()))
|
||||
|
||||
api.WriteSuccessResponseHeadersOnly(w)
|
||||
}
|
||||
|
||||
func isLockEnabled(header http.Header) bool {
|
||||
lockEnabledStr := header.Get(api.AmzBucketObjectLockEnabled)
|
||||
lockEnabled, _ := strconv.ParseBool(lockEnabledStr)
|
||||
return lockEnabled
|
||||
}
|
||||
|
||||
func checkBucketName(bucketName string) error {
|
||||
if len(bucketName) < 3 || len(bucketName) > 63 {
|
||||
return errors.GetAPIError(errors.ErrInvalidBucketName)
|
||||
|
|
|
@ -46,6 +46,7 @@ const (
|
|||
AmzGrantWrite = "X-Amz-Grant-Write"
|
||||
AmzExpectedBucketOwner = "X-Amz-Expected-Bucket-Owner"
|
||||
AmzSourceExpectedBucketOwner = "X-Amz-Source-Expected-Bucket-Owner"
|
||||
AmzBucketObjectLockEnabled = "X-Amz-Bucket-Object-Lock-Enabled"
|
||||
|
||||
ContainerID = "X-Container-Id"
|
||||
|
||||
|
|
|
@ -27,13 +27,17 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
const locationConstraintAttr = ".s3-location-constraint"
|
||||
const (
|
||||
attributeLocationConstraint = ".s3-location-constraint"
|
||||
attributeLockEnabled = "LockEnabled"
|
||||
)
|
||||
|
||||
func (n *layer) containerInfo(ctx context.Context, idCnr *cid.ID) (*data.BucketInfo, error) {
|
||||
var (
|
||||
err error
|
||||
res *container.Container
|
||||
rid = api.GetRequestID(ctx)
|
||||
log = n.log.With(zap.Stringer("cid", idCnr), zap.String("request_id", rid))
|
||||
|
||||
info = &data.BucketInfo{
|
||||
CID: idCnr,
|
||||
|
@ -42,10 +46,7 @@ func (n *layer) containerInfo(ctx context.Context, idCnr *cid.ID) (*data.BucketI
|
|||
)
|
||||
res, err = n.neoFS.Container(ctx, *idCnr)
|
||||
if err != nil {
|
||||
n.log.Error("could not fetch container",
|
||||
zap.Stringer("cid", idCnr),
|
||||
zap.String("request_id", rid),
|
||||
zap.Error(err))
|
||||
log.Error("could not fetch container", zap.Error(err))
|
||||
|
||||
if strings.Contains(err.Error(), "container not found") {
|
||||
return nil, errors.GetAPIError(errors.ErrNoSuchBucket)
|
||||
|
@ -63,26 +64,27 @@ func (n *layer) containerInfo(ctx context.Context, idCnr *cid.ID) (*data.BucketI
|
|||
case container.AttributeTimestamp:
|
||||
unix, err := strconv.ParseInt(attr.Value(), 10, 64)
|
||||
if err != nil {
|
||||
n.log.Error("could not parse container creation time",
|
||||
zap.Stringer("cid", idCnr),
|
||||
zap.String("request_id", rid),
|
||||
zap.String("created_at", val),
|
||||
zap.Error(err))
|
||||
log.Error("could not parse container creation time",
|
||||
zap.String("created_at", val), zap.Error(err))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
info.Created = time.Unix(unix, 0)
|
||||
case locationConstraintAttr:
|
||||
case attributeLocationConstraint:
|
||||
info.LocationConstraint = val
|
||||
case attributeLockEnabled:
|
||||
info.ObjectLockEnabled, err = strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
log.Error("could not parse container object lock enabled attribute",
|
||||
zap.String("lock_enabled", val), zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := n.bucketCache.Put(info); err != nil {
|
||||
n.log.Warn("could not put bucket info into cache",
|
||||
zap.Stringer("cid", idCnr),
|
||||
zap.String("bucket_name", info.Name),
|
||||
zap.Error(err))
|
||||
if err = n.bucketCache.Put(info); err != nil {
|
||||
log.Warn("could not put bucket info into cache",
|
||||
zap.String("bucket_name", info.Name), zap.Error(err))
|
||||
}
|
||||
|
||||
return info, nil
|
||||
|
@ -133,9 +135,10 @@ func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*ci
|
|||
|
||||
if p.LocationConstraint != "" {
|
||||
locConstAttr = container.NewAttribute()
|
||||
locConstAttr.SetKey(locationConstraintAttr)
|
||||
locConstAttr.SetKey(attributeLocationConstraint)
|
||||
locConstAttr.SetValue(p.LocationConstraint)
|
||||
}
|
||||
//todo add lock enabled attr
|
||||
|
||||
if bktInfo.CID, err = n.neoFS.CreateContainer(ctx, PrmContainerCreate{
|
||||
Creator: *bktInfo.Owner,
|
||||
|
|
|
@ -336,6 +336,7 @@ type (
|
|||
EACL *eacl.Table
|
||||
SessionToken *session.Token
|
||||
LocationConstraint string
|
||||
ObjectLockEnabled bool
|
||||
}
|
||||
// PutBucketACLParams stores put bucket acl request parameters.
|
||||
PutBucketACLParams struct {
|
||||
|
|
Loading…
Reference in a new issue