From ba84cd90712d3db4e1fc98e272a0e12474a6d0d6 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 6 Sep 2019 22:14:14 +0800 Subject: [PATCH] fix: allow set object acl in batch --- cmd/climc/shell/buckets.go | 11 +++------ pkg/cloudcommon/db/paging.go | 14 +++++++++++ pkg/cloudprovider/objectstore.go | 15 ++++++++++-- pkg/compute/models/buckets.go | 42 ++++++++++++++++++++++++-------- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/cmd/climc/shell/buckets.go b/cmd/climc/shell/buckets.go index 8771780e02..060fd151e3 100644 --- a/cmd/climc/shell/buckets.go +++ b/cmd/climc/shell/buckets.go @@ -213,15 +213,12 @@ func init() { }) type BucketSetAclOptions struct { - ID string `help:"ID or name of bucket" json:"-"` - ACL string `help:"ACL to set" choices:"default|private|public-read|public-read-write"` - Key string `help:"Optional object key"` + ID string `help:"ID or name of bucket" json:"-"` + ACL string `help:"ACL to set" choices:"default|private|public-read|public-read-write" json:"acl"` + Key []string `help:"Optional object key" json:"key"` } R(&BucketSetAclOptions{}, "bucket-set-acl", "Set ACL of bucket or object", func(s *mcclient.ClientSession, args *BucketSetAclOptions) error { - params, err := options.StructToParams(args) - if err != nil { - return err - } + params := jsonutils.Marshal(args) result, err := modules.Buckets.PerformAction(s, args.ID, "acl", params) if err != nil { return err diff --git a/pkg/cloudcommon/db/paging.go b/pkg/cloudcommon/db/paging.go index 852164b10b..292b5620c3 100644 --- a/pkg/cloudcommon/db/paging.go +++ b/pkg/cloudcommon/db/paging.go @@ -1,3 +1,17 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package db import ( diff --git a/pkg/cloudprovider/objectstore.go b/pkg/cloudprovider/objectstore.go index 1c834b622a..5c73aa2ed1 100644 --- a/pkg/cloudprovider/objectstore.go +++ b/pkg/cloudprovider/objectstore.go @@ -23,6 +23,7 @@ import ( "strings" "time" + "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" "yunion.io/x/s3cli" @@ -166,15 +167,25 @@ type ICloudObject interface { SetAcl(acl TBucketACLType) error } -func ICloudObject2BaseCloudObject(obj ICloudObject) SBaseCloudObject { - return SBaseCloudObject{ +func ICloudObject2JSONObject(obj ICloudObject) jsonutils.JSONObject { + obj2 := struct { + Key string + SizeBytes int64 + StorageClass string + ETag string + LastModified time.Time + ContentType string + Acl string + }{ Key: obj.GetKey(), SizeBytes: obj.GetSizeBytes(), StorageClass: obj.GetStorageClass(), ETag: obj.GetETag(), LastModified: obj.GetLastModified(), ContentType: obj.GetContentType(), + Acl: string(obj.GetAcl()), } + return jsonutils.Marshal(obj2) } func (o *SBaseCloudObject) GetKey() string { diff --git a/pkg/compute/models/buckets.go b/pkg/compute/models/buckets.go index 3891eedab3..f0d4c11ebf 100644 --- a/pkg/compute/models/buckets.go +++ b/pkg/compute/models/buckets.go @@ -599,7 +599,7 @@ func (bucket *SBucket) GetDetailsObjects( } retArray := jsonutils.NewArray() for i := range objects { - retArray.Add(jsonutils.Marshal(cloudprovider.ICloudObject2BaseCloudObject(objects[i]))) + retArray.Add(cloudprovider.ICloudObject2JSONObject(objects[i])) } ret := jsonutils.NewDict() ret.Add(retArray, "objects") @@ -882,7 +882,6 @@ func (bucket *SBucket) PerformAcl( data jsonutils.JSONObject, ) (jsonutils.JSONObject, error) { aclStr, _ := data.GetString("acl") - objKey, _ := data.GetString("key") switch cloudprovider.TBucketACLType(aclStr) { case cloudprovider.ACLPrivate, cloudprovider.ACLAuthRead, cloudprovider.ACLPublicRead, cloudprovider.ACLPublicReadWrite: // do nothing @@ -895,7 +894,8 @@ func (bucket *SBucket) PerformAcl( return nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err) } - if len(objKey) == 0 { + objKey, _ := data.Get("key") + if objKey == nil { err = iBucket.SetAcl(cloudprovider.TBucketACLType(aclStr)) if err != nil { return nil, httperrors.NewInternalServerError("setAcl error %s", err) @@ -905,16 +905,38 @@ func (bucket *SBucket) PerformAcl( if err != nil { return nil, httperrors.NewInternalServerError("syncWithCloudBucket error %s", err) } - } else { - object, err := cloudprovider.GetIObject(iBucket, objKey) - if err != nil { - if err == cloudprovider.ErrNotFound { - return nil, httperrors.NewResourceNotFoundError("object %s not found", objKey) - } else { + return nil, nil + } + var keys []string + switch jsonObj := objKey.(type) { + case *jsonutils.JSONString: + key, _ := jsonObj.GetString() + keys = []string{key} + case *jsonutils.JSONArray: + keys = jsonObj.GetStringArray() + } + var objects []cloudprovider.ICloudObject + for _, key := range keys { + if strings.HasSuffix(key, "/") { + objs, err := cloudprovider.GetIObjects(iBucket, key, true) + if err != nil { return nil, httperrors.NewInternalServerError("iBucket.GetIObjects error %s", err) } + objects = append(objects, objs...) + } else { + object, err := cloudprovider.GetIObject(iBucket, key) + if err != nil { + if err == cloudprovider.ErrNotFound { + return nil, httperrors.NewResourceNotFoundError("object %s not found", objKey) + } else { + return nil, httperrors.NewInternalServerError("iBucket.GetIObject error %s", err) + } + } + objects = append(objects, object) } - err = object.SetAcl(cloudprovider.TBucketACLType(aclStr)) + } + for _, object := range objects { + err := object.SetAcl(cloudprovider.TBucketACLType(aclStr)) if err != nil { return nil, httperrors.NewInternalServerError("setAcl error %s", err) }