s3object.go 5.9 KB

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