yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/google/s3object.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Copyright 2019 Yunion
    16  
    17  //
    18  // Licensed under the Apache License, Version 2.0 (the "License");
    19  // you may not use this file except in compliance with the License.
    20  // You may obtain a copy of the License at
    21  //
    22  //     http://www.apache.org/licenses/LICENSE-2.0
    23  //
    24  // Unless required by applicable law or agreed to in writing, software
    25  // distributed under the License is distributed on an "AS IS" BASIS,
    26  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    27  // See the License for the specific language governing permissions and
    28  // limitations under the License.
    29  
    30  package google
    31  
    32  import (
    33  	"context"
    34  	"fmt"
    35  	"net/http"
    36  	"net/url"
    37  	"strings"
    38  	"time"
    39  
    40  	"cloud.google.com/go/storage"
    41  
    42  	"yunion.io/x/jsonutils"
    43  	"yunion.io/x/log"
    44  	"yunion.io/x/pkg/errors"
    45  
    46  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    47  )
    48  
    49  type SBucketObjects struct {
    50  	Prefixes      []string
    51  	Items         []SObject
    52  	NextPageToken string
    53  }
    54  
    55  type SObject struct {
    56  	bucket *SBucket
    57  
    58  	Id                      string
    59  	Name                    string
    60  	SelfLink                string
    61  	MediaLink               string
    62  	Bucket                  string
    63  	Generation              string
    64  	Metageneration          string
    65  	ContentType             string
    66  	ContentEncoding         string
    67  	ContentDisposition      string
    68  	ContentLanguage         string
    69  	CacheControl            string
    70  	StorageClass            string
    71  	Size                    int64
    72  	Md5Hash                 string
    73  	Metadata                map[string]string
    74  	Crc32c                  string
    75  	Etag                    string
    76  	TimeCreated             time.Time
    77  	Updated                 time.Time
    78  	TimeStorageClassUpdated time.Time
    79  }
    80  
    81  func (region *SRegion) GetObjects(bucket string, prefix string, nextPageToken string, delimiter string, maxCount int) (*SBucketObjects, error) {
    82  	if maxCount <= 0 {
    83  		maxCount = 20
    84  	}
    85  	resource := fmt.Sprintf("b/%s/o", bucket)
    86  	params := map[string]string{"maxResults": fmt.Sprintf("%d", maxCount)}
    87  	if len(prefix) > 0 {
    88  		params["prefix"] = prefix
    89  	}
    90  	if len(delimiter) > 0 {
    91  		params["delimiter"] = delimiter
    92  	}
    93  	if len(nextPageToken) > 0 {
    94  		params["pageToken"] = nextPageToken
    95  	}
    96  	objs := SBucketObjects{}
    97  	resp, err := region.client.storageList(resource, params)
    98  	if err != nil {
    99  		return nil, errors.Wrap(err, "storageList")
   100  	}
   101  	err = resp.Unmarshal(&objs)
   102  	if err != nil {
   103  		return nil, errors.Wrap(err, "Unmarshal")
   104  	}
   105  	return &objs, nil
   106  }
   107  
   108  func (region *SRegion) ConvertAcl(acls []GCSAcl) cloudprovider.TBucketACLType {
   109  	ret := cloudprovider.ACLPrivate
   110  	for _, acl := range acls {
   111  		if acl.Entity == string(storage.AllUsers) {
   112  			if acl.Role == string(storage.RoleOwner) || acl.Role == string(storage.RoleWriter) {
   113  				ret = cloudprovider.ACLPublicReadWrite
   114  			}
   115  			if acl.Role == string(storage.RoleReader) && ret != cloudprovider.ACLPublicReadWrite {
   116  				ret = cloudprovider.ACLPublicRead
   117  			}
   118  		}
   119  		if !(ret == cloudprovider.ACLPublicRead || ret == cloudprovider.ACLPublicReadWrite) && acl.Entity == string(storage.AllAuthenticatedUsers) {
   120  			ret = cloudprovider.ACLAuthRead
   121  		}
   122  	}
   123  	return ret
   124  }
   125  
   126  func (o *SObject) GetAcl() cloudprovider.TBucketACLType {
   127  	if strings.HasSuffix(o.Name, "/") {
   128  		return cloudprovider.ACLPrivate
   129  	}
   130  	acls, err := o.bucket.region.GetObjectAcl(o.bucket.Name, o.Name)
   131  	if err != nil {
   132  		log.Errorf("failed to get object %s acls error: %v", o.Name, err)
   133  		return cloudprovider.ACLUnknown
   134  	}
   135  	return o.bucket.region.ConvertAcl(acls)
   136  }
   137  
   138  func (o *SObject) SetAcl(acl cloudprovider.TBucketACLType) error {
   139  	return o.bucket.region.SetObjectAcl(o.bucket.Name, o.Name, acl)
   140  }
   141  
   142  func (o *SObject) GetIBucket() cloudprovider.ICloudBucket {
   143  	return o.bucket
   144  }
   145  
   146  func (o *SObject) GetKey() string {
   147  	return o.Name
   148  }
   149  
   150  func (o *SObject) GetSizeBytes() int64 {
   151  	return o.Size
   152  }
   153  
   154  func (o *SObject) GetLastModified() time.Time {
   155  	return o.Updated
   156  }
   157  
   158  func (o *SObject) GetStorageClass() string {
   159  	return o.StorageClass
   160  }
   161  
   162  func (o *SObject) GetETag() string {
   163  	return o.Etag
   164  }
   165  
   166  func (o *SObject) GetMeta() http.Header {
   167  	meta := http.Header{}
   168  	for k, v := range o.Metadata {
   169  		meta.Set(k, v)
   170  	}
   171  	for k, v := range map[string]string{
   172  		cloudprovider.META_HEADER_CONTENT_TYPE:        o.ContentType,
   173  		cloudprovider.META_HEADER_CONTENT_ENCODING:    o.ContentEncoding,
   174  		cloudprovider.META_HEADER_CONTENT_DISPOSITION: o.ContentDisposition,
   175  		cloudprovider.META_HEADER_CONTENT_LANGUAGE:    o.ContentLanguage,
   176  		cloudprovider.META_HEADER_CACHE_CONTROL:       o.CacheControl,
   177  	} {
   178  		meta.Set(k, v)
   179  	}
   180  	return meta
   181  }
   182  
   183  func (region *SRegion) SetObjectMeta(bucket, object string, meta http.Header) error {
   184  	body := map[string]string{}
   185  	for k := range meta {
   186  		switch k {
   187  		case cloudprovider.META_HEADER_CONTENT_TYPE:
   188  			body["contentType"] = meta.Get(k)
   189  		case cloudprovider.META_HEADER_CONTENT_ENCODING:
   190  			body["contentEncoding"] = meta.Get(k)
   191  		case cloudprovider.META_HEADER_CONTENT_DISPOSITION:
   192  			body["contentDisposition"] = meta.Get(k)
   193  		case cloudprovider.META_HEADER_CONTENT_LANGUAGE:
   194  			body["contentLanguage"] = meta.Get(k)
   195  		case cloudprovider.META_HEADER_CACHE_CONTROL:
   196  			body["cacheControl"] = meta.Get(k)
   197  		default:
   198  			body[fmt.Sprintf("metadata.%s", k)] = meta.Get(k)
   199  		}
   200  	}
   201  	resource := fmt.Sprintf("b/%s/o/%s", bucket, url.PathEscape(object))
   202  	return region.StoragePut(resource, jsonutils.Marshal(body), nil)
   203  }
   204  
   205  func (o *SObject) SetMeta(ctx context.Context, meta http.Header) error {
   206  	return o.bucket.region.SetObjectMeta(o.bucket.Name, o.Name, meta)
   207  }