client.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. // Copyright 2022 Google LLC
  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. package storage
  15. import (
  16. "context"
  17. "io"
  18. "time"
  19. "cloud.google.com/go/iam/apiv1/iampb"
  20. gax "github.com/googleapis/gax-go/v2"
  21. "google.golang.org/api/option"
  22. )
  23. // TODO(noahdietz): Move existing factory methods to this file.
  24. // storageClient is an internal-only interface designed to separate the
  25. // transport-specific logic of making Storage API calls from the logic of the
  26. // client library.
  27. //
  28. // Implementation requirements beyond implementing the interface include:
  29. // * factory method(s) must accept a `userProject string` param
  30. // * `settings` must be retained per instance
  31. // * `storageOption`s must be resolved in the order they are received
  32. // * all API errors must be wrapped in the gax-go APIError type
  33. // * any unimplemented interface methods must return a StorageUnimplementedErr
  34. //
  35. // TODO(noahdietz): This interface is currently not used in the production code
  36. // paths
  37. type storageClient interface {
  38. // Top-level methods.
  39. GetServiceAccount(ctx context.Context, project string, opts ...storageOption) (string, error)
  40. CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, enableObjectRetention *bool, opts ...storageOption) (*BucketAttrs, error)
  41. ListBuckets(ctx context.Context, project string, opts ...storageOption) *BucketIterator
  42. Close() error
  43. // Bucket methods.
  44. DeleteBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error
  45. GetBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error)
  46. UpdateBucket(ctx context.Context, bucket string, uattrs *BucketAttrsToUpdate, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error)
  47. LockBucketRetentionPolicy(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error
  48. ListObjects(ctx context.Context, bucket string, q *Query, opts ...storageOption) *ObjectIterator
  49. // Object metadata methods.
  50. DeleteObject(ctx context.Context, bucket, object string, gen int64, conds *Conditions, opts ...storageOption) error
  51. GetObject(ctx context.Context, bucket, object string, gen int64, encryptionKey []byte, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error)
  52. UpdateObject(ctx context.Context, params *updateObjectParams, opts ...storageOption) (*ObjectAttrs, error)
  53. // Default Object ACL methods.
  54. DeleteDefaultObjectACL(ctx context.Context, bucket string, entity ACLEntity, opts ...storageOption) error
  55. ListDefaultObjectACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error)
  56. UpdateDefaultObjectACL(ctx context.Context, bucket string, entity ACLEntity, role ACLRole, opts ...storageOption) error
  57. // Bucket ACL methods.
  58. DeleteBucketACL(ctx context.Context, bucket string, entity ACLEntity, opts ...storageOption) error
  59. ListBucketACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error)
  60. UpdateBucketACL(ctx context.Context, bucket string, entity ACLEntity, role ACLRole, opts ...storageOption) error
  61. // Object ACL methods.
  62. DeleteObjectACL(ctx context.Context, bucket, object string, entity ACLEntity, opts ...storageOption) error
  63. ListObjectACLs(ctx context.Context, bucket, object string, opts ...storageOption) ([]ACLRule, error)
  64. UpdateObjectACL(ctx context.Context, bucket, object string, entity ACLEntity, role ACLRole, opts ...storageOption) error
  65. // Media operations.
  66. ComposeObject(ctx context.Context, req *composeObjectRequest, opts ...storageOption) (*ObjectAttrs, error)
  67. RewriteObject(ctx context.Context, req *rewriteObjectRequest, opts ...storageOption) (*rewriteObjectResponse, error)
  68. NewRangeReader(ctx context.Context, params *newRangeReaderParams, opts ...storageOption) (*Reader, error)
  69. OpenWriter(params *openWriterParams, opts ...storageOption) (*io.PipeWriter, error)
  70. // IAM methods.
  71. GetIamPolicy(ctx context.Context, resource string, version int32, opts ...storageOption) (*iampb.Policy, error)
  72. SetIamPolicy(ctx context.Context, resource string, policy *iampb.Policy, opts ...storageOption) error
  73. TestIamPermissions(ctx context.Context, resource string, permissions []string, opts ...storageOption) ([]string, error)
  74. // HMAC Key methods.
  75. GetHMACKey(ctx context.Context, project, accessID string, opts ...storageOption) (*HMACKey, error)
  76. ListHMACKeys(ctx context.Context, project, serviceAccountEmail string, showDeletedKeys bool, opts ...storageOption) *HMACKeysIterator
  77. UpdateHMACKey(ctx context.Context, project, serviceAccountEmail, accessID string, attrs *HMACKeyAttrsToUpdate, opts ...storageOption) (*HMACKey, error)
  78. CreateHMACKey(ctx context.Context, project, serviceAccountEmail string, opts ...storageOption) (*HMACKey, error)
  79. DeleteHMACKey(ctx context.Context, project, accessID string, opts ...storageOption) error
  80. // Notification methods.
  81. ListNotifications(ctx context.Context, bucket string, opts ...storageOption) (map[string]*Notification, error)
  82. CreateNotification(ctx context.Context, bucket string, n *Notification, opts ...storageOption) (*Notification, error)
  83. DeleteNotification(ctx context.Context, bucket string, id string, opts ...storageOption) error
  84. }
  85. // settings contains transport-agnostic configuration for API calls made via
  86. // the storageClient inteface. All implementations must utilize settings
  87. // and respect those that are applicable.
  88. type settings struct {
  89. // retry is the complete retry configuration to use when evaluating if an
  90. // API call should be retried.
  91. retry *retryConfig
  92. // gax is a set of gax.CallOption to be conveyed to gax.Invoke.
  93. // Note: Not all storageClient interfaces will must use gax.Invoke.
  94. gax []gax.CallOption
  95. // idempotent indicates if the call is idempotent or not when considering
  96. // if the call should be retired or not.
  97. idempotent bool
  98. // clientOption is a set of option.ClientOption to be used during client
  99. // transport initialization. See https://pkg.go.dev/google.golang.org/api/option
  100. // for a list of supported options.
  101. clientOption []option.ClientOption
  102. // userProject is the user project that should be billed for the request.
  103. userProject string
  104. }
  105. func initSettings(opts ...storageOption) *settings {
  106. s := &settings{}
  107. resolveOptions(s, opts...)
  108. return s
  109. }
  110. func resolveOptions(s *settings, opts ...storageOption) {
  111. for _, o := range opts {
  112. o.Apply(s)
  113. }
  114. }
  115. // callSettings is a helper for resolving storage options against the settings
  116. // in the context of an individual call. This is to ensure that client-level
  117. // default settings are not mutated by two different calls getting options.
  118. //
  119. // Example: s := callSettings(c.settings, opts...)
  120. func callSettings(defaults *settings, opts ...storageOption) *settings {
  121. if defaults == nil {
  122. return nil
  123. }
  124. // This does not make a deep copy of the pointer/slice fields, but all
  125. // options replace the settings fields rather than modify their values in
  126. // place.
  127. cs := *defaults
  128. resolveOptions(&cs, opts...)
  129. return &cs
  130. }
  131. // makeStorageOpts is a helper for generating a set of storageOption based on
  132. // idempotency, retryConfig, and userProject. All top-level client operations
  133. // will generally have to pass these options through the interface.
  134. func makeStorageOpts(isIdempotent bool, retry *retryConfig, userProject string) []storageOption {
  135. opts := []storageOption{idempotent(isIdempotent)}
  136. if retry != nil {
  137. opts = append(opts, withRetryConfig(retry))
  138. }
  139. if userProject != "" {
  140. opts = append(opts, withUserProject(userProject))
  141. }
  142. return opts
  143. }
  144. // storageOption is the transport-agnostic call option for the storageClient
  145. // interface.
  146. type storageOption interface {
  147. Apply(s *settings)
  148. }
  149. func withGAXOptions(opts ...gax.CallOption) storageOption {
  150. return &gaxOption{opts}
  151. }
  152. type gaxOption struct {
  153. opts []gax.CallOption
  154. }
  155. func (o *gaxOption) Apply(s *settings) { s.gax = o.opts }
  156. func withRetryConfig(rc *retryConfig) storageOption {
  157. return &retryOption{rc}
  158. }
  159. type retryOption struct {
  160. rc *retryConfig
  161. }
  162. func (o *retryOption) Apply(s *settings) { s.retry = o.rc }
  163. func idempotent(i bool) storageOption {
  164. return &idempotentOption{i}
  165. }
  166. type idempotentOption struct {
  167. idempotency bool
  168. }
  169. func (o *idempotentOption) Apply(s *settings) { s.idempotent = o.idempotency }
  170. func withClientOptions(opts ...option.ClientOption) storageOption {
  171. return &clientOption{opts: opts}
  172. }
  173. type clientOption struct {
  174. opts []option.ClientOption
  175. }
  176. func (o *clientOption) Apply(s *settings) { s.clientOption = o.opts }
  177. func withUserProject(project string) storageOption {
  178. return &userProjectOption{project}
  179. }
  180. type userProjectOption struct {
  181. project string
  182. }
  183. func (o *userProjectOption) Apply(s *settings) { s.userProject = o.project }
  184. type openWriterParams struct {
  185. // Writer configuration
  186. // ctx is the context used by the writer routine to make all network calls
  187. // and to manage the writer routine - see `Writer.ctx`.
  188. // Required.
  189. ctx context.Context
  190. // chunkSize - see `Writer.ChunkSize`.
  191. // Optional.
  192. chunkSize int
  193. // chunkRetryDeadline - see `Writer.ChunkRetryDeadline`.
  194. // Optional.
  195. chunkRetryDeadline time.Duration
  196. // Object/request properties
  197. // bucket - see `Writer.o.bucket`.
  198. // Required.
  199. bucket string
  200. // attrs - see `Writer.ObjectAttrs`.
  201. // Required.
  202. attrs *ObjectAttrs
  203. // forceEmptyContentType - Disables auto-detect of Content-Type
  204. // Optional.
  205. forceEmptyContentType bool
  206. // conds - see `Writer.o.conds`.
  207. // Optional.
  208. conds *Conditions
  209. // encryptionKey - see `Writer.o.encryptionKey`
  210. // Optional.
  211. encryptionKey []byte
  212. // sendCRC32C - see `Writer.SendCRC32C`.
  213. // Optional.
  214. sendCRC32C bool
  215. // Writer callbacks
  216. // donec - see `Writer.donec`.
  217. // Required.
  218. donec chan struct{}
  219. // setError callback for reporting errors - see `Writer.error`.
  220. // Required.
  221. setError func(error)
  222. // progress callback for reporting upload progress - see `Writer.progress`.
  223. // Required.
  224. progress func(int64)
  225. // setObj callback for reporting the resulting object - see `Writer.obj`.
  226. // Required.
  227. setObj func(*ObjectAttrs)
  228. }
  229. type newRangeReaderParams struct {
  230. bucket string
  231. conds *Conditions
  232. encryptionKey []byte
  233. gen int64
  234. length int64
  235. object string
  236. offset int64
  237. readCompressed bool // Use accept-encoding: gzip. Only works for HTTP currently.
  238. }
  239. type updateObjectParams struct {
  240. bucket, object string
  241. uattrs *ObjectAttrsToUpdate
  242. gen int64
  243. encryptionKey []byte
  244. conds *Conditions
  245. overrideRetention *bool
  246. }
  247. type composeObjectRequest struct {
  248. dstBucket string
  249. dstObject destinationObject
  250. srcs []sourceObject
  251. predefinedACL string
  252. sendCRC32C bool
  253. }
  254. type sourceObject struct {
  255. name string
  256. bucket string
  257. gen int64
  258. conds *Conditions
  259. encryptionKey []byte
  260. }
  261. type destinationObject struct {
  262. name string
  263. bucket string
  264. conds *Conditions
  265. attrs *ObjectAttrs // attrs to set on the destination object.
  266. encryptionKey []byte
  267. keyName string
  268. }
  269. type rewriteObjectRequest struct {
  270. srcObject sourceObject
  271. dstObject destinationObject
  272. predefinedACL string
  273. token string
  274. maxBytesRewrittenPerCall int64
  275. }
  276. type rewriteObjectResponse struct {
  277. resource *ObjectAttrs
  278. done bool
  279. written int64
  280. size int64
  281. token string
  282. }