Google Cloud Storage C++ Client  1.42.0
A C++ Client Library for Google Cloud Storage
client.h
Go to the documentation of this file.
1 // Copyright 2018 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 // https://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 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
17 
18 #include "google/cloud/storage/hmac_key_metadata.h"
19 #include "google/cloud/storage/internal/group_options.h"
20 #include "google/cloud/storage/internal/logging_client.h"
21 #include "google/cloud/storage/internal/parameter_pack_validation.h"
22 #include "google/cloud/storage/internal/policy_document_request.h"
23 #include "google/cloud/storage/internal/retry_client.h"
24 #include "google/cloud/storage/internal/signed_url_requests.h"
25 #include "google/cloud/storage/internal/tuple_filter.h"
26 #include "google/cloud/storage/list_buckets_reader.h"
27 #include "google/cloud/storage/list_hmac_keys_reader.h"
28 #include "google/cloud/storage/list_objects_and_prefixes_reader.h"
29 #include "google/cloud/storage/list_objects_reader.h"
30 #include "google/cloud/storage/notification_event_type.h"
31 #include "google/cloud/storage/notification_payload_format.h"
32 #include "google/cloud/storage/oauth2/google_credentials.h"
33 #include "google/cloud/storage/object_rewriter.h"
34 #include "google/cloud/storage/object_stream.h"
35 #include "google/cloud/storage/retry_policy.h"
36 #include "google/cloud/storage/upload_options.h"
37 #include "google/cloud/storage/version.h"
38 #include "google/cloud/internal/throw_delegate.h"
39 #include "google/cloud/options.h"
40 #include "google/cloud/status.h"
41 #include "google/cloud/status_or.h"
42 #include "absl/meta/type_traits.h"
43 #include <string>
44 #include <type_traits>
45 #include <vector>
46 
47 namespace google {
48 namespace cloud {
49 namespace storage {
51 namespace internal {
52 class NonResumableParallelUploadState;
53 class ResumableParallelUploadState;
54 struct ClientImplDetails;
55 } // namespace internal
56 /**
57  * The Google Cloud Storage (GCS) Client.
58  *
59  * This is the main class to interact with GCS. It provides member functions to
60  * invoke all the APIs in the service.
61  *
62  * @par Performance
63  * Creating an object of this type is a relatively low-cost operation.
64  * Connections to the service are created on demand. Copy-assignment and
65  * copy-construction are also relatively low-cost operations, they should be
66  * comparable to copying a few shared pointers. The first request (or any
67  * request that requires a new connection) incurs the cost of creating the
68  * connection and authenticating with the service. Note that the library may
69  * need to perform other bookkeeping operations that may impact performance.
70  * For example, access tokens need to be refreshed from time to time, and this
71  * may impact the performance of some operations.
72  *
73  * @par Connection Pool
74  * By default this class uses HTTPS to communicate with the service. Creating a
75  * new HTTPS session is relatively expensive, as it must go through the TCP/IP
76  * and SSL handshakes. To minimize this overhead the class maintains a
77  * connection pool to the service. After each request completes the connection
78  * is returned to the pool, and reused in future requests. Note that for
79  * downloads (implemented by the ReadObject() member function) the connection
80  * remains in use until the download completes. Therefore, having multiple
81  * downloads open at the same time requires multiple connections.
82  *
83  * The application can limit the maximum size of this connection pool using
84  * `storage::ConnectionPoolSizeOption`. If returning a connection to the pool
85  * would make the pool larger than this limit then the oldest connection in the
86  * pool is closed (recall that all connections in the pool are inactive). Note
87  * that this is the maximum size of the pool, the client library does not create
88  * connections until needed.
89  *
90  * Note that the application may (at times) use more connections than the
91  * maximum size of the pool. For example if N downloads are in progress the
92  * library may need N connections, even if the the pool size is smaller.
93  *
94  * Two clients that compare equal share the same connection pool. Two clients
95  * created with the default constructor or with the constructor from a
96  * `google::cloud::Options` are never equal and do not share connection pools.
97  * Clients created via copy (or move) construction compare equal and share the
98  * connection pool.
99  *
100  * @par Thread-safety
101  * Instances of this class created via copy-construction or copy-assignment
102  * share the underlying pool of connections. Access to these copies via multiple
103  * threads is guaranteed to work. Two threads operating on the same instance of
104  * this class is not guaranteed to work.
105  *
106  * @par Credentials
107  * The default approach for creating a Client uses Google Application Default
108  * Credentials (ADCs). Note that a default-constructed client uses the ADCs:
109  *
110  * @snippet storage_client_initialization_samples.cc default-client
111  *
112  * Finding or loading the ADCs can fail. This will result in run-time errors
113  * when making requests.
114  *
115  * If you prefer to explicitly load the ADCs use:
116  *
117  * @snippet storage_client_initialization_samples.cc explicit-adcs
118  *
119  * To load a service account credentials key file use:
120  *
121  * @snippet storage_client_initialization_samples.cc service-account-keyfile
122  *
123  * Other credential types are available, including:
124  *
125  * - `google::cloud::MakeInsecureCredentials()` for anonymous access to public
126  * GCS buckets or objects.
127  * - `google::cloud::MakeAccessTokenCredentials()` to use an access token
128  * obtained through any out-of-band mechanism.
129  * - `google::cloud::MakeImpersonateServiceAccountCredentials()` to use the IAM
130  * credentials service and [impersonate a service account].
131  * - `google::cloud::MakeServiceAccountCredentials()` to use a service account
132  * key file.
133  *
134  * [impersonate service account]:
135  * https://cloud.google.com/iam/docs/impersonating-service-accounts
136  *
137  * @par Error Handling
138  * This class uses `StatusOr<T>` to report errors. When an operation fails to
139  * perform its work the returned `StatusOr<T>` contains the error details. If
140  * the `ok()` member function in the `StatusOr<T>` returns `true` then it
141  * contains the expected result. Please consult the [`StatusOr<T>`
142  * documentation](#google::cloud::StatusOr) for more details.
143  *
144  * @code
145  * namespace gcs = google::cloud::storage;
146  * gcs::Client client = ...;
147  * google::cloud::StatusOr<gcs::BucketMetadata> bucket_metadata =
148  * client.GetBucketMetadata("my-bucket");
149  *
150  * if (!bucket_metadata) {
151  * std::cerr << "Error getting metadata for my-bucket: "
152  * << bucket_metadata.status() << "\n";
153  * return;
154  * }
155  *
156  * // Use bucket_metadata as a smart pointer here, e.g.:
157  * std::cout << "The generation for " << bucket_metadata->name() " is "
158  * << bucket_metadata->generation() << "\n";
159  * @endcode
160  *
161  * In addition, the @ref index "main page" contains examples using `StatusOr<T>`
162  * to handle errors.
163  *
164  * @par Optional Request Options
165  * Most of the member functions in this class can receive optional request
166  * options. For example, the default when reading multi-version objects is to
167  * retrieve the latest version:
168  *
169  * @code
170  * auto stream = gcs.ReadObject("my-bucket", "my-object");
171  * @endcode
172  *
173  * Some applications may want to retrieve specific versions. In this case
174  * just provide the `Generation` request option:
175  *
176  * @code
177  * auto stream = gcs.ReadObject(
178  * "my-bucket", "my-object", gcs::Generation(generation));
179  * @endcode
180  *
181  * Each function documents the types accepted as optional request options. These
182  * parameters can be specified in any order. Specifying a request option that is
183  * not applicable to a member function results in a compile-time error.
184  *
185  * All operations support the following common request options:
186  *
187  * - `Fields`: return a [partial response], which includes only the desired
188  * fields.
189  * - `QuotaUser`: attribute the request to this specific label for quota
190  * purposes.
191  * - `UserProject`: change the request costs (if applicable) to this GCP
192  * project.
193  * - `CustomHeader`: include a custom header with the request. These are
194  * typically used for testing, though they are sometimes helpful if
195  * environments where HTTPS traffic is mediated by a proxy.
196  * - `IfMatchEtag`: a pre-condition, the operation succeeds only if the resource
197  * ETag matches. Typically used in OCC loops ("change X only if its Etag is
198  * still Y"). Note that GCS sometimes ignores this header, we recommend you
199  * use the GCS specific pre-conditions (e.g., `IfGenerationMatch`,
200  * `IfMetagenerationMatch` and their `*NotMatch` counterparts) instead.
201  * - `IfNoneMatchEtag`: a pre-condition, abort the operation if the resource
202  * ETag has not changed. Typically used in caching ("return the contents of X
203  * only if the Etag is different from the last value I got, which was Y").
204  * Note that GCS sometimes ignores this header, we recommend you use the GCS
205  * specific pre-conditions (e.g., `IfGenerationMatch`, `IfMetagenerationMatch`
206  * and their `*NotMatch` counterparts) instead.
207  * - `UserIp`: attribute the request to this specific IP address for quota
208  * purpose. Not recommended, prefer `QuotaUser` instead.
209  *
210  * [partial response]:
211  * https://cloud.google.com/storage/docs/json_api#partial-response
212  *
213  * @par Per-operation Overrides
214  *
215  * In addition to the request options, which are passed on to the service to
216  * modify the request, you can specify options that override the local behavior
217  * of the library. For example, you can override the local retry policy:
218  *
219  * @snippet storage_client_per_operation_samples.cc change-retry-policy
220  *
221  * @par Retry, Backoff, and Idempotency Policies
222  *
223  * The library automatically retries requests that fail with transient errors,
224  * and follows the [recommended practice][exponential-backoff] to backoff
225  * between retries.
226  *
227  * The default policies are to continue retrying for up to 15 minutes, and to
228  * use truncated (at 5 minutes) exponential backoff, doubling the maximum
229  * backoff period between retries. Likewise, the idempotency policy is
230  * configured to retry all operations.
231  *
232  * The application can override these policies when constructing objects of this
233  * class. The documentation for the constructors show examples of this in
234  * action.
235  *
236  * [exponential-backoff]:
237  * https://cloud.google.com/storage/docs/exponential-backoff
238  *
239  * @see https://cloud.google.com/storage/ for an overview of GCS.
240  *
241  * @see https://cloud.google.com/storage/docs/key-terms for an introduction of
242  * the key terms used in GCS.
243  *
244  * @see https://cloud.google.com/storage/docs/json_api/ for an overview of the
245  * underlying API.
246  *
247  * @see https://cloud.google.com/docs/authentication/production for details
248  * about Application Default %Credentials.
249  *
250  * @see #google::cloud::StatusOr.
251  *
252  * @see `LimitedTimeRetryPolicy` and `LimitedErrorCountRetryPolicy` for
253  * alternative retry policies.
254  *
255  * @see `ExponentialBackoffPolicy` to configure different parameters for the
256  * exponential backoff policy.
257  *
258  * @see `AlwaysRetryIdempotencyPolicy` and `StrictIdempotencyPolicy` for
259  * alternative idempotency policies.
260  */
261 class Client {
262  public:
263  /**
264  * Build a new client.
265  *
266  * @param opts the configuration parameters for the `Client`.
267  *
268  * @see #ClientOptionList for a list of useful options.
269  *
270  * @par Idempotency Policy Example
271  * @snippet storage_object_samples.cc insert object strict idempotency
272  *
273  * @par Modified Retry Policy Example
274  * @snippet storage_object_samples.cc insert object modified retry
275  *
276  * @par Change Credentials Example
277  * @snippet storage_client_initialization_samples.cc service-account-keyfile
278  */
279  explicit Client(Options opts = {});
280 
281  /// @name Equality
282  ///@{
283  friend bool operator==(Client const& a, Client const& b) {
284  return a.raw_client_ == b.raw_client_;
285  }
286  friend bool operator!=(Client const& a, Client const& b) { return !(a == b); }
287  ///@}
288 
289  /**
290  * @name Bucket operations.
291  *
292  * Buckets are the basic containers that hold your data. Everything that you
293  * store in GCS must be contained in a bucket. You can use buckets to organize
294  * your data and control access to your data, but unlike directories and
295  * folders, you cannot nest buckets.
296  *
297  * @see https://cloud.google.com/storage/docs/key-terms#buckets for more
298  * information about GCS buckets.
299  */
300  ///@{
301  /**
302  * Fetches the list of buckets for a given project.
303  *
304  * @param project_id the project to query.
305  * @param options a list of optional query parameters and/or request headers.
306  * Valid types for this operation include `MaxResults`, `Prefix`,
307  * `Projection`, and `UserProject`.
308  *
309  * @par Idempotency
310  * This is a read-only operation and is always idempotent.
311  *
312  * @par Example
313  * @snippet storage_bucket_samples.cc list buckets for project
314  */
315  template <typename... Options>
316  ListBucketsReader ListBucketsForProject(std::string const& project_id,
317  Options&&... options) {
318  google::cloud::internal::OptionsSpan const span(
319  SpanOptions(std::forward<Options>(options)...));
320  internal::ListBucketsRequest request(project_id);
321  request.set_multiple_options(std::forward<Options>(options)...);
322  auto& client = raw_client_;
323  return google::cloud::internal::MakePaginationRange<ListBucketsReader>(
324  request,
325  [client](internal::ListBucketsRequest const& r) {
326  return client->ListBuckets(r);
327  },
328  [](internal::ListBucketsResponse r) { return std::move(r.items); });
329  }
330 
331  /**
332  * Fetches the list of buckets for the default project.
333  *
334  * The default project is required to be configured in the `ClientOptions`
335  * used to construct this object. If the application does not set the project
336  * id in the `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is
337  * used. If neither the environment variable is set, nor a value is set
338  * explicitly by the application, the returned `ListBucketsReader` will
339  * return an error status when used.
340  *
341  * @param options a list of optional query parameters and/or request headers.
342  * Valid types for this operation include `MaxResults`, `Prefix`,
343  * `Projection`, and `UserProject`.
344  *
345  * @par Idempotency
346  * This is a read-only operation and is always idempotent.
347  *
348  * @par Example
349  * @snippet storage_bucket_samples.cc list buckets
350  */
351  template <typename... Options>
352  ListBucketsReader ListBuckets(Options&&... options) {
353  google::cloud::internal::OptionsSpan const span(
354  SpanOptions(std::forward<Options>(options)...));
355  auto const& project_id = raw_client_->client_options().project_id();
356  return ListBucketsForProject(project_id, std::forward<Options>(options)...);
357  }
358 
359  /**
360  * Creates a new Google Cloud Storage bucket using the default project. If
361  * the default project is not configured the server will reject the request,
362  * and this function returns the error status.
363  *
364  * @param bucket_name the name of the new bucket.
365  * @param metadata the metadata for the new Bucket. The `name` field is
366  * ignored in favor of @p bucket_name.
367  * @param options a list of optional query parameters and/or request headers.
368  * Valid types for this operation include `PredefinedAcl`,
369  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
370  *
371  * @par Idempotency
372  * This operation is always idempotent. It fails if the bucket already exists.
373  *
374  * @par Example
375  * @snippet storage_bucket_samples.cc create bucket
376  *
377  * @see Before enabling Uniform Bucket Level Access please review the
378  * [feature documentation][ubla-link], as well as
379  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
380  *
381  * [ubla-link]:
382  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
383  * [ubla-should-link]:
384  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
385  */
386  template <typename... Options>
387  StatusOr<BucketMetadata> CreateBucket(std::string bucket_name,
388  BucketMetadata metadata,
389  Options&&... options) {
390  auto const& project_id = raw_client_->client_options().project_id();
391  return CreateBucketForProject(std::move(bucket_name), project_id,
392  std::move(metadata),
393  std::forward<Options>(options)...);
394  }
395 
396  /**
397  * Creates a new Google Cloud Storage Bucket in a given project.
398  *
399  * @param bucket_name the name of the new bucket.
400  * @param project_id the id of the project that will host the new bucket.
401  * @param metadata the metadata for the new Bucket. The `name` field is
402  * ignored in favor of @p bucket_name.
403  * @param options a list of optional query parameters and/or request headers.
404  * Valid types for this operation include `PredefinedAcl`,
405  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
406  *
407  * @par Idempotency
408  * This operation is always idempotent. It fails if the bucket already exists.
409  *
410  * @par Example
411  * @snippet storage_bucket_samples.cc create bucket for project
412  *
413  * @see Before enabling Uniform Bucket Level Access please review the
414  * [feature documentation][ubla-link], as well as
415  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
416  *
417  * [ubla-link]:
418  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
419  * [ubla-should-link]:
420  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
421  */
422  template <typename... Options>
423  StatusOr<BucketMetadata> CreateBucketForProject(std::string bucket_name,
424  std::string project_id,
425  BucketMetadata metadata,
426  Options&&... options) {
427  google::cloud::internal::OptionsSpan const span(
428  SpanOptions(std::forward<Options>(options)...));
429  metadata.set_name(std::move(bucket_name));
430  internal::CreateBucketRequest request(std::move(project_id),
431  std::move(metadata));
432  request.set_multiple_options(std::forward<Options>(options)...);
433  return raw_client_->CreateBucket(request);
434  }
435 
436  /**
437  * Fetches the bucket metadata.
438  *
439  * @param bucket_name query metadata information about this bucket.
440  * @param options a list of optional query parameters and/or request headers.
441  * Valid types for this operation include `IfMetagenerationMatch`,
442  * `IfMetagenerationNotMatch`, `UserProject`, and `Projection`.
443  *
444  * @par Idempotency
445  * This is a read-only operation and is always idempotent.
446  *
447  * @par Example
448  * @snippet storage_bucket_samples.cc get bucket metadata
449  */
450  template <typename... Options>
451  StatusOr<BucketMetadata> GetBucketMetadata(std::string const& bucket_name,
452  Options&&... options) {
453  google::cloud::internal::OptionsSpan const span(
454  SpanOptions(std::forward<Options>(options)...));
455  internal::GetBucketMetadataRequest request(bucket_name);
456  request.set_multiple_options(std::forward<Options>(options)...);
457  return raw_client_->GetBucketMetadata(request);
458  }
459 
460  /**
461  * Deletes a Google Cloud Storage Bucket.
462  *
463  * @param bucket_name the bucket to be deleted.
464  * @param options a list of optional query parameters and/or request headers.
465  * Valid types for this operation include `IfMetagenerationMatch`,
466  * `IfMetagenerationNotMatch`, and `UserProject`.
467  *
468  * @par Idempotency
469  * This operation is only idempotent if restricted by pre-conditions, in this
470  * case, `IfMetagenerationMatch`.
471  *
472  * @par Example
473  * @snippet storage_bucket_samples.cc delete bucket
474  */
475  template <typename... Options>
476  Status DeleteBucket(std::string const& bucket_name, Options&&... options) {
477  google::cloud::internal::OptionsSpan const span(
478  SpanOptions(std::forward<Options>(options)...));
479  internal::DeleteBucketRequest request(bucket_name);
480  request.set_multiple_options(std::forward<Options>(options)...);
481  return raw_client_->DeleteBucket(request).status();
482  }
483 
484  /**
485  * Updates the metadata in a Google Cloud Storage Bucket.
486  *
487  * A `Buckets: update` request changes *all* the writeable attributes of a
488  * bucket, in contrast, a `Buckets: patch` request only changes the subset of
489  * the attributes included in the request. This function creates a
490  * `Buckets: update` request to change the writable attributes in
491  * `BucketMetadata`.
492  *
493  * @param bucket_name the name of the new bucket.
494  * @param metadata the new metadata for the Bucket. The `name` field is
495  * ignored in favor of @p bucket_name.
496  * @param options a list of optional query parameters and/or request headers.
497  * Valid types for this operation include `IfMetagenerationMatch`,
498  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
499  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
500  *
501  * @par Idempotency
502  * This operation is only idempotent if restricted by pre-conditions, in this
503  * case,`IfMetagenerationMatch`.
504  *
505  * @par Example
506  * @snippet storage_bucket_samples.cc update bucket
507  *
508  * @see Before enabling Uniform Bucket Level Access please review the
509  * [feature documentation][ubla-link], as well as
510  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
511  *
512  * [ubla-link]:
513  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
514  * [ubla-should-link]:
515  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
516  */
517  template <typename... Options>
518  StatusOr<BucketMetadata> UpdateBucket(std::string bucket_name,
519  BucketMetadata metadata,
520  Options&&... options) {
521  google::cloud::internal::OptionsSpan const span(
522  SpanOptions(std::forward<Options>(options)...));
523  metadata.set_name(std::move(bucket_name));
524  internal::UpdateBucketRequest request(std::move(metadata));
525  request.set_multiple_options(std::forward<Options>(options)...);
526  return raw_client_->UpdateBucket(request);
527  }
528 
529  /**
530  * Computes the difference between two BucketMetadata objects and patches a
531  * bucket based on that difference.
532  *
533  * A `Buckets: update` request changes *all* the writeable attributes of a
534  * bucket, in contrast, a `Buckets: patch` request only changes the subset of
535  * the attributes included in the request.
536  *
537  * This function creates a patch request to change the writeable attributes in
538  * @p original to the values in @p updated. Non-writeable attributes are
539  * ignored, and attributes not present in @p updated are removed. Typically
540  * this function is used after the application obtained a value with
541  * `GetBucketMetadata` and has modified these parameters.
542  *
543  * @param bucket_name the bucket to be updated.
544  * @param original the initial value of the bucket metadata.
545  * @param updated the updated value for the bucket metadata.
546  * @param options a list of optional query parameters and/or request headers.
547  * Valid types for this operation include `IfMetagenerationMatch`,
548  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
549  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
550  *
551  * @par Idempotency
552  * This operation is only idempotent if restricted by pre-conditions, in this
553  * case, `IfMetagenerationMatch`.
554  *
555  * @par Example
556  * @snippet storage_bucket_samples.cc patch bucket storage class
557  *
558  * @see Before enabling Uniform Bucket Level Access please review the
559  * [feature documentation][ubla-link], as well as
560  * ["Should you use uniform bucket-level access?"][ubla-should-link].
561  *
562  * [ubla-link]:
563  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
564  * [ubla-should-link]:
565  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
566  */
567  template <typename... Options>
568  StatusOr<BucketMetadata> PatchBucket(std::string bucket_name,
569  BucketMetadata const& original,
570  BucketMetadata const& updated,
571  Options&&... options) {
572  google::cloud::internal::OptionsSpan const span(
573  SpanOptions(std::forward<Options>(options)...));
574  internal::PatchBucketRequest request(std::move(bucket_name), original,
575  updated);
576  request.set_multiple_options(std::forward<Options>(options)...);
577  return raw_client_->PatchBucket(request);
578  }
579 
580  /**
581  * Patches the metadata in a Google Cloud Storage Bucket given a desired set
582  * changes.
583  *
584  * A `Buckets: update` request changes *all* the writeable attributes of a
585  * bucket, in contrast, a `Buckets: patch` request only changes the subset of
586  * the attributes included in the request. This function creates a patch
587  * request based on the given `BucketMetadataPatchBuilder` which represents
588  * the desired set of changes.
589  *
590  * @param bucket_name the bucket to be updated.
591  * @param builder the set of updates to perform in the Bucket.
592  * @param options a list of optional query parameters and/or request headers.
593  * Valid types for this operation include `IfMetagenerationMatch`,
594  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
595  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
596  *
597  * @par Idempotency
598  * This operation is only idempotent if restricted by pre-conditions, in this
599  * case, `IfMetagenerationMatch`.
600  *
601  * @par Example
602  * @snippet storage_bucket_samples.cc patch bucket storage class with builder
603  *
604  * @see Before enabling Uniform Bucket Level Access please review the
605  * [feature documentation][ubla-link], as well as
606  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
607  *
608  * [ubla-link]:
609  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
610  * [ubla-should-link]:
611  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
612  */
613  template <typename... Options>
615  std::string bucket_name, BucketMetadataPatchBuilder const& builder,
616  Options&&... options) {
617  google::cloud::internal::OptionsSpan const span(
618  SpanOptions(std::forward<Options>(options)...));
619  internal::PatchBucketRequest request(std::move(bucket_name), builder);
620  request.set_multiple_options(std::forward<Options>(options)...);
621  return raw_client_->PatchBucket(request);
622  }
623 
624  /**
625  * Fetches the native
626  * [IAM policy](@ref google::cloud::storage::NativeIamPolicy) for a Bucket.
627  *
628  * Google Cloud Identity & Access Management (IAM) lets administrators
629  * authorize who can take action on specific resources, including Google
630  * Cloud Storage Buckets. This operation allows you to query the IAM policies
631  * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
632  * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
633  * documentation describes
634  * [the
635  * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
636  * between legacy Bucket ACLs and IAM policies.
637  *
638  * Consult
639  * [the
640  * documentation](https://cloud.google.com/storage/docs/access-control/iam)
641  * for a more detailed description of IAM policies and their use in
642  * Google Cloud Storage.
643  *
644  * @param bucket_name query metadata information about this bucket.
645  * @param options a list of optional query parameters and/or request headers.
646  * Valid types for this operation include `UserProject`.
647  *
648  * @par Idempotency
649  * This is a read-only operation and is always idempotent.
650  *
651  * @par Example
652  * @snippet storage_bucket_iam_samples.cc native get bucket iam policy
653  *
654  * @see #google::cloud::storage::NativeIamPolicy for details about the
655  * `NativeIamPolicy` class.
656  */
657  template <typename... Options>
659  std::string const& bucket_name, Options&&... options) {
660  google::cloud::internal::OptionsSpan const span(
661  SpanOptions(std::forward<Options>(options)...));
662  internal::GetBucketIamPolicyRequest request(bucket_name);
663  request.set_multiple_options(std::forward<Options>(options)...);
664  return raw_client_->GetNativeBucketIamPolicy(request);
665  }
666 
667  /**
668  * Sets the native
669  * [IAM Policy](@ref google::cloud::storage::NativeIamPolicy) for a Bucket.
670  *
671  * Google Cloud Identity & Access Management (IAM) lets administrators
672  * authorize who can take action on specific resources, including Google
673  * Cloud Storage Buckets. This operation allows you to set the IAM policies
674  * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
675  * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
676  * documentation describes
677  * [the
678  * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
679  * between legacy Bucket ACLs and IAM policies.
680  *
681  * Consult
682  * [the
683  * documentation](https://cloud.google.com/storage/docs/access-control/iam)
684  * for a more detailed description of IAM policies their use in
685  * Google Cloud Storage.
686  *
687  * @note The server rejects requests where the ETag value of the policy does
688  * not match the current ETag. Effectively this means that applications must
689  * use `GetNativeBucketIamPolicy()` to fetch the current value and ETag
690  * before calling `SetNativeBucketIamPolicy()`. Applications should use
691  * optimistic concurrency control techniques to retry changes in case some
692  * other application modified the IAM policy between the
693  * `GetNativeBucketIamPolicy` and `SetNativeBucketIamPolicy` calls.
694  *
695  * @param bucket_name query metadata information about this bucket.
696  * @param iam_policy the new IAM policy.
697  * @param options a list of optional query parameters and/or request headers.
698  * Valid types for this operation include `UserProject`.
699  *
700  * @par Idempotency
701  * This operation is only idempotent if restricted by pre-conditions, in this
702  * case, `IfMetagenerationMatch`.
703  *
704  * @par Example: adding a new member
705  * @snippet storage_bucket_iam_samples.cc native add bucket iam member
706  *
707  * @par Example: removing a IAM member
708  * @snippet storage_bucket_iam_samples.cc native remove bucket iam member
709  *
710  * @see #google::cloud::storage::NativeIamPolicy for details about the
711  * `NativeIamPolicy` class.
712  */
713  template <typename... Options>
715  std::string const& bucket_name, NativeIamPolicy const& iam_policy,
716  Options&&... options) {
717  google::cloud::internal::OptionsSpan const span(
718  SpanOptions(std::forward<Options>(options)...));
719  internal::SetNativeBucketIamPolicyRequest request(bucket_name, iam_policy);
720  request.set_multiple_options(std::forward<Options>(options)...);
721  return raw_client_->SetNativeBucketIamPolicy(request);
722  }
723 
724  /**
725  * Tests the IAM permissions of the caller against a Bucket.
726  *
727  * Google Cloud Identity & Access Management (IAM) lets administrators
728  * authorize who can take action on specific resources, including Google
729  * Cloud Storage Buckets. This operation tests the permissions of the caller
730  * for a Bucket. You must provide a list of permissions, this API will return
731  * the subset of those permissions that the current caller has in the given
732  * Bucket.
733  *
734  * Consult
735  * [the
736  * documentation](https://cloud.google.com/storage/docs/access-control/iam)
737  * for a more detailed description of IAM policies their use in
738  * Google Cloud Storage.
739  *
740  * @param bucket_name query metadata information about this bucket.
741  * @param permissions the list of permissions to check.
742  * @param options a list of optional query parameters and/or request headers.
743  * Valid types for this operation include `UserProject`.
744  *
745  * @par Idempotency
746  * This is a read-only operation and is always idempotent.
747  *
748  * @par Example
749  * @snippet storage_bucket_iam_samples.cc test bucket iam permissions
750  */
751  template <typename... Options>
752  StatusOr<std::vector<std::string>> TestBucketIamPermissions(
753  std::string bucket_name, std::vector<std::string> permissions,
754  Options&&... options) {
755  google::cloud::internal::OptionsSpan const span(
756  SpanOptions(std::forward<Options>(options)...));
757  internal::TestBucketIamPermissionsRequest request(std::move(bucket_name),
758  std::move(permissions));
759  request.set_multiple_options(std::forward<Options>(options)...);
760  auto result = raw_client_->TestBucketIamPermissions(request);
761  if (!result) {
762  return std::move(result).status();
763  }
764  return std::move(result.value().permissions);
765  }
766 
767  /**
768  * Locks the retention policy for a bucket.
769  *
770  * @warning Locking a retention policy is an irreversible action. Once locked,
771  * you must delete the entire bucket in order to "remove" the bucket's
772  * retention policy. However, before you can delete the bucket, you must
773  * be able to delete all the objects in the bucket, which itself is only
774  * possible if all the objects have reached the retention period set by
775  * the retention policy.
776  *
777  * The [Bucket Lock
778  * feature](https://cloud.google.com/storage/docs/bucket-lock) allows you to
779  * configure a data retention policy for a Cloud Storage bucket that governs
780  * how long objects in the bucket must be retained. The feature also allows
781  * you to lock the data retention policy, permanently preventing the policy
782  * from being reduced or removed.
783  *
784  * @param bucket_name the name of the bucket.
785  * @param metageneration the expected value of the metageneration on the
786  * bucket. The request will fail if the metageneration does not match the
787  * current value.
788  * @param options a list of optional query parameters and/or request headers.
789  * Valid types for this operation include `UserProject`.
790  *
791  * @par Idempotency
792  * This operation is always idempotent because the `metageneration` parameter
793  * is always required, and it acts as a pre-condition on the operation.
794  *
795  * @par Example: lock the retention policy
796  * @snippet storage_retention_policy_samples.cc lock retention policy
797  *
798  * @par Example: get the current retention policy
799  * @snippet storage_retention_policy_samples.cc get retention policy
800  *
801  * @par Example: set the current retention policy
802  * @snippet storage_retention_policy_samples.cc set retention policy
803  *
804  * @par Example: remove the retention policy
805  * @snippet storage_retention_policy_samples.cc remove retention policy
806  *
807  * @see https://cloud.google.com/storage/docs/bucket-lock for a description of
808  * the Bucket Lock feature.
809  *
810  * @see https://cloud.google.com/storage/docs/using-bucket-lock for examples
811  * of how to use the Bucket Lock and retention policy features.
812  */
813  template <typename... Options>
815  std::string const& bucket_name, std::uint64_t metageneration,
816  Options&&... options) {
817  google::cloud::internal::OptionsSpan const span(
818  SpanOptions(std::forward<Options>(options)...));
819  internal::LockBucketRetentionPolicyRequest request(bucket_name,
820  metageneration);
821  request.set_multiple_options(std::forward<Options>(options)...);
822  return raw_client_->LockBucketRetentionPolicy(request);
823  }
824  ///@}
825 
826  /**
827  * @name Object operations
828  *
829  * Objects are the individual pieces of data that you store in GCS. Objects
830  * have two components: *object data* and *object metadata*. Object data
831  * (sometimes referred to as *media*) is typically a file that you want
832  * to store in GCS. Object metadata is information that describe various
833  * object qualities.
834  *
835  * @see https://cloud.google.com/storage/docs/key-terms#objects for more
836  * information about GCS objects.
837  */
838  ///@{
839  /**
840  * Creates an object given its name and contents.
841  *
842  * @param bucket_name the name of the bucket that will contain the object.
843  * @param object_name the name of the object to be created.
844  * @param contents the contents (media) for the new object.
845  * @param options a list of optional query parameters and/or request headers.
846  * Valid types for this operation include `ContentEncoding`,
847  * `ContentType`, `Crc32cChecksumValue`, `DisableCrc32cChecksum`,
848  * `DisableMD5Hash`, `EncryptionKey`, `IfGenerationMatch`,
849  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
850  * `IfMetagenerationNotMatch`, `KmsKeyName`, `MD5HashValue`,
851  * `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
852  *
853  * @par Idempotency
854  * This operation is only idempotent if restricted by pre-conditions, in this
855  * case, `IfGenerationMatch`.
856  *
857  * @par Example
858  * @snippet storage_object_samples.cc insert object
859  *
860  * @par Example
861  * @snippet storage_object_samples.cc insert object multipart
862  */
863  template <typename... Options>
864  StatusOr<ObjectMetadata> InsertObject(std::string const& bucket_name,
865  std::string const& object_name,
866  std::string contents,
867  Options&&... options) {
868  google::cloud::internal::OptionsSpan const span(
869  SpanOptions(std::forward<Options>(options)...));
870  internal::InsertObjectMediaRequest request(bucket_name, object_name,
871  std::move(contents));
872  request.set_multiple_options(std::forward<Options>(options)...);
873  return raw_client_->InsertObjectMedia(request);
874  }
875 
876  /**
877  * Copies an existing object.
878  *
879  * Use `CopyObject` to copy between objects in the same location and storage
880  * class. Copying objects across locations or storage classes can fail for
881  * large objects and retrying the operation will not succeed.
882  *
883  * @note Prefer using `RewriteObject()` to copy objects, `RewriteObject()` can
884  * copy objects to different locations, with different storage class,
885  * and/or with different encryption keys.
886  *
887  * @param source_bucket_name the name of the bucket that contains the object
888  * to be copied.
889  * @param source_object_name the name of the object to copy.
890  * @param destination_bucket_name the name of the bucket that will contain the
891  * new object.
892  * @param destination_object_name the name of the new object.
893  * @param options a list of optional query parameters and/or request headers.
894  * Valid types for this operation include `DestinationKmsKeyName`,
895  * `DestinationPredefinedAcl`,`EncryptionKey`,`IfGenerationMatch`,
896  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
897  * `IfMetagenerationNotMatch`, `IfSourceGenerationMatch`,
898  * `IfSourceGenerationNotMatch`, `IfSourceMetagenerationMatch`,
899  * `IfSourceMetagenerationNotMatch`, `Projection`, `SourceGeneration`,
900  * `SourceEncryptionKey`, `UserProject`, and `WithObjectMetadata`.
901  *
902  * @par Idempotency
903  * This operation is only idempotent if restricted by pre-conditions, in this
904  * case, `IfGenerationMatch`.
905  *
906  * @par Example
907  * @snippet storage_object_samples.cc copy object
908  *
909  * @par Example: copy an encrypted object
910  * @snippet storage_object_csek_samples.cc copy encrypted object
911  *
912  * @see https://cloud.google.com/storage/docs/json_api/v1/objects/copy for
913  * a full description of the advantages of `Objects: rewrite` over
914  * `Objects: copy`.
915  */
916  template <typename... Options>
917  StatusOr<ObjectMetadata> CopyObject(std::string source_bucket_name,
918  std::string source_object_name,
919  std::string destination_bucket_name,
920  std::string destination_object_name,
921  Options&&... options) {
922  google::cloud::internal::OptionsSpan const span(
923  SpanOptions(std::forward<Options>(options)...));
924  internal::CopyObjectRequest request(
925  std::move(source_bucket_name), std::move(source_object_name),
926  std::move(destination_bucket_name), std::move(destination_object_name));
927  request.set_multiple_options(std::forward<Options>(options)...);
928  return raw_client_->CopyObject(request);
929  }
930 
931  /**
932  * Fetches the object metadata.
933  *
934  * @param bucket_name the bucket containing the object.
935  * @param object_name the object name.
936  * @param options a list of optional query parameters and/or request headers.
937  * Valid types for this operation include `Generation`,
938  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
939  * `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
940  *
941  * @par Idempotency
942  * This is a read-only operation and is always idempotent.
943  *
944  * @par Example
945  * @snippet storage_object_samples.cc get object metadata
946  */
947  template <typename... Options>
948  StatusOr<ObjectMetadata> GetObjectMetadata(std::string const& bucket_name,
949  std::string const& object_name,
950  Options&&... options) {
951  google::cloud::internal::OptionsSpan const span(
952  SpanOptions(std::forward<Options>(options)...));
953  internal::GetObjectMetadataRequest request(bucket_name, object_name);
954  request.set_multiple_options(std::forward<Options>(options)...);
955  return raw_client_->GetObjectMetadata(request);
956  }
957 
958  /**
959  * Lists the objects in a bucket.
960  *
961  * @param bucket_name the name of the bucket to list.
962  * @param options a list of optional query parameters and/or request headers.
963  * Valid types for this operation include `MaxResults`, `Prefix`,
964  * `Delimiter`, `IncludeTrailingDelimiter`, `StartOffset`, `EndOffset`,
965  * `Projection`, `UserProject`, and `Versions`.
966  *
967  * @par Idempotency
968  * This is a read-only operation and is always idempotent.
969  *
970  * @par Example
971  * @snippet storage_object_samples.cc list objects
972  */
973  template <typename... Options>
974  ListObjectsReader ListObjects(std::string const& bucket_name,
975  Options&&... options) {
976  google::cloud::internal::OptionsSpan const span(
977  SpanOptions(std::forward<Options>(options)...));
978  internal::ListObjectsRequest request(bucket_name);
979  request.set_multiple_options(std::forward<Options>(options)...);
980  auto& client = raw_client_;
981  return google::cloud::internal::MakePaginationRange<ListObjectsReader>(
982  request,
983  [client](internal::ListObjectsRequest const& r) {
984  return client->ListObjects(r);
985  },
986  [](internal::ListObjectsResponse r) { return std::move(r.items); });
987  }
988 
989  /**
990  * Lists the objects and prefixes in a bucket.
991  *
992  * @param bucket_name the name of the bucket to list.
993  * @param options a list of optional query parameters and/or request headers.
994  * Valid types for this operation include
995  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `UserProject`,
996  * `Projection`, `Prefix`, `Delimiter`, `IncludeTrailingDelimiter`,
997  * `StartOffset`, `EndOffset`, and `Versions`.
998  *
999  * @par Idempotency
1000  * This is a read-only operation and is always idempotent.
1001  *
1002  * @par Example
1003  * @snippet storage_object_samples.cc list objects and prefixes
1004  */
1005  template <typename... Options>
1006  ListObjectsAndPrefixesReader ListObjectsAndPrefixes(
1007  std::string const& bucket_name, Options&&... options) {
1008  google::cloud::internal::OptionsSpan const span(
1009  SpanOptions(std::forward<Options>(options)...));
1010  internal::ListObjectsRequest request(bucket_name);
1011  request.set_multiple_options(std::forward<Options>(options)...);
1012  auto& client = raw_client_;
1013  return google::cloud::internal::MakePaginationRange<
1014  ListObjectsAndPrefixesReader>(
1015  request,
1016  [client](internal::ListObjectsRequest const& r) {
1017  return client->ListObjects(r);
1018  },
1019  [](internal::ListObjectsResponse r) {
1020  std::vector<ObjectOrPrefix> result;
1021  for (auto& item : r.items) {
1022  result.emplace_back(std::move(item));
1023  }
1024  for (auto& prefix : r.prefixes) {
1025  result.emplace_back(std::move(prefix));
1026  }
1027  internal::SortObjectsAndPrefixes(result);
1028  return result;
1029  });
1030  }
1031 
1032  /**
1033  * Reads the contents of an object.
1034  *
1035  * Returns an object derived from `std::istream` which can be used to read the
1036  * contents of the GCS blob. The application should check the `badbit` (e.g.
1037  * by calling `stream.bad()`) on the returned object to detect if there was
1038  * an error reading from the blob. If `badbit` is set, the application can
1039  * check the `status()` variable to get details about the failure.
1040  * Applications can also set the exception mask on the returned stream, in
1041  * which case an exception is thrown if an error is detected.
1042  *
1043  * @param bucket_name the name of the bucket that contains the object.
1044  * @param object_name the name of the object to be read.
1045  * @param options a list of optional query parameters and/or request headers.
1046  * Valid types for this operation include `DisableCrc32cChecksum`,
1047  * `DisableMD5Hash`, `EncryptionKey`, `Generation`, `IfGenerationMatch`,
1048  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1049  * `IfMetagenerationNotMatch`, `ReadFromOffset`, `ReadRange`, `ReadLast`,
1050  * `UserProject`, and `AcceptEncoding`.
1051  *
1052  * @par Idempotency
1053  * This is a read-only operation and is always idempotent.
1054  *
1055  * @par Example
1056  * @snippet storage_object_samples.cc read object
1057  *
1058  * @par Example: read only a sub-range in the object.
1059  * @snippet storage_object_samples.cc read object range
1060  *
1061  * @par Example: read a object encrypted with a CSEK.
1062  * @snippet storage_object_csek_samples.cc read encrypted object
1063  *
1064  * @par Example: disable decompressive transcoding.
1065  * @snippet storage_object_samples.cc read object gzip
1066  */
1067  template <typename... Options>
1068  ObjectReadStream ReadObject(std::string const& bucket_name,
1069  std::string const& object_name,
1070  Options&&... options) {
1071  struct HasReadRange
1072  : public absl::disjunction<std::is_same<ReadRange, Options>...> {};
1073  struct HasReadFromOffset
1074  : public absl::disjunction<std::is_same<ReadFromOffset, Options>...> {};
1075  struct HasReadLast
1076  : public absl::disjunction<std::is_same<ReadLast, Options>...> {};
1077 
1078  struct HasIncompatibleRangeOptions
1079  : public std::integral_constant<bool, HasReadLast::value &&
1080  (HasReadFromOffset::value ||
1081  HasReadRange::value)> {};
1082 
1083  static_assert(!HasIncompatibleRangeOptions::value,
1084  "Cannot set ReadLast option with either ReadFromOffset or "
1085  "ReadRange.");
1086 
1087  google::cloud::internal::OptionsSpan const span(
1088  SpanOptions(std::forward<Options>(options)...));
1089  internal::ReadObjectRangeRequest request(bucket_name, object_name);
1090  request.set_multiple_options(std::forward<Options>(options)...);
1091  return ReadObjectImpl(request);
1092  }
1093 
1094  /**
1095  * Writes contents into an object.
1096  *
1097  * This creates a `std::ostream` object to upload contents. The application
1098  * can use either the regular `operator<<()`, or `std::ostream::write()` to
1099  * upload data.
1100  *
1101  * This function always uses [resumable uploads][resumable-link]. The
1102  * application can provide a `#RestoreResumableUploadSession()` option to
1103  * resume a previously created upload. The returned object has accessors to
1104  * query the session id and the next byte expected by GCS.
1105  *
1106  * @note When resuming uploads it is the application's responsibility to save
1107  * the session id to restart the upload later. Likewise, it is the
1108  * application's responsibility to query the next expected byte and send
1109  * the remaining data without gaps or duplications.
1110  *
1111  * For small uploads we recommend using `InsertObject`, consult
1112  * [the documentation][how-to-upload-link] for details.
1113  *
1114  * If the application does not provide a `#RestoreResumableUploadSession()`
1115  * option, or it provides the `#NewResumableUploadSession()` option then a new
1116  * resumable upload session is created.
1117  *
1118  * More information about buffering and recommendations around performance in
1119  * the `ObjectWriteStream` class documentation.
1120  *
1121  * @param bucket_name the name of the bucket that contains the object.
1122  * @param object_name the name of the object to be read.
1123  * @param options a list of optional query parameters and/or request headers.
1124  * Valid types for this operation include `ContentEncoding`, `ContentType`,
1125  * `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
1126  * `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
1127  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
1128  * `MD5HashValue`, `PredefinedAcl`, `Projection`,
1129  * `UseResumableUploadSession`, `UserProject`, `WithObjectMetadata`,
1130  * `UploadContentLength`, `AutoFinalize`, and `UploadBufferSize`.
1131  *
1132  * @par Idempotency
1133  * This operation is only idempotent if restricted by pre-conditions, in this
1134  * case, `IfGenerationMatch`.
1135  *
1136  * @par Example
1137  * @snippet storage_object_samples.cc write object
1138  *
1139  * @par Example: write an object with a CMEK.
1140  * @snippet storage_object_cmek_samples.cc write object with kms key
1141  *
1142  * @par Example: starting a resumable upload.
1143  * @snippet storage_object_resumable_write_samples.cc start resumable upload
1144  *
1145  * @par Example: resuming a resumable upload.
1146  * @snippet storage_object_resumable_write_samples.cc resume resumable upload
1147  *
1148  * @see [Resumable Uploads][resumable-link] for more information about
1149  * resumable uploads.
1150  *
1151  * [resumable-link]: https://cloud.google.com/storage/docs/resumable-uploads
1152  * [how-to-upload-link]:
1153  * https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload
1154  */
1155  template <typename... Options>
1156  ObjectWriteStream WriteObject(std::string const& bucket_name,
1157  std::string const& object_name,
1158  Options&&... options) {
1159  google::cloud::internal::OptionsSpan const span(
1160  SpanOptions(std::forward<Options>(options)...));
1161  internal::ResumableUploadRequest request(bucket_name, object_name);
1162  request.set_multiple_options(std::forward<Options>(options)...);
1163  return WriteObjectImpl(request);
1164  }
1165 
1166  /**
1167  * Uploads a file to an object.
1168  *
1169  * @note
1170  * Only regular files are supported. If you need to upload the results of
1171  * reading a device, Named Pipe, FIFO, or other type of file system object
1172  * that is **not** a regular file then `WriteObject()` is probably a better
1173  * alternative.
1174  *
1175  * @param file_name the name of the file to be uploaded.
1176  * @param bucket_name the name of the bucket that contains the object.
1177  * @param object_name the name of the object to be read.
1178  * @param options a list of optional query parameters and/or request headers.
1179  * Valid types for this operation include `ContentEncoding`, `ContentType`,
1180  * `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
1181  * `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
1182  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
1183  * `MD5HashValue`, `PredefinedAcl`, `Projection`, `UserProject`,
1184  * `UploadFromOffset`, `UploadLimit` and `WithObjectMetadata`.
1185  *
1186  * @par Idempotency
1187  * This operation is only idempotent if restricted by pre-conditions, in this
1188  * case, `IfGenerationMatch`.
1189  *
1190  * @par Example
1191  * @snippet storage_object_file_transfer_samples.cc upload file
1192  *
1193  * @par Example: manually selecting a resumable upload
1194  * @snippet storage_object_file_transfer_samples.cc upload file resumable
1195  */
1196  template <typename... Options>
1197  StatusOr<ObjectMetadata> UploadFile(std::string const& file_name,
1198  std::string const& bucket_name,
1199  std::string const& object_name,
1200  Options&&... options) {
1201  // Determine, at compile time, which version of UploadFileImpl we should
1202  // call. This needs to be done at compile time because ObjectInsertMedia
1203  // does not support (nor should it support) the UseResumableUploadSession
1204  // option.
1205  using HasUseResumableUpload =
1206  absl::disjunction<std::is_same<UseResumableUploadSession, Options>...>;
1207  return UploadFileImpl(file_name, bucket_name, object_name,
1208  HasUseResumableUpload{},
1209  std::forward<Options>(options)...);
1210  }
1211 
1212  /**
1213  * Cancel a resumable upload.
1214  *
1215  * @param upload_session_url the url of the upload session. Returned by
1216  * `ObjectWriteStream::resumable_session_id`.
1217  * @param options a list of optional query parameters and/or request headers.
1218  * Valid types for this operation include `UserProject`.
1219  *
1220  * @par Idempotency
1221  * This operation is always idempotent because it only acts on a specific
1222  * `upload_session_url`.
1223  */
1224  template <typename... Options>
1225  Status DeleteResumableUpload(std::string const& upload_session_url,
1226  Options&&... options) {
1227  google::cloud::internal::OptionsSpan const span(
1228  SpanOptions(std::forward<Options>(options)...));
1229  internal::DeleteResumableUploadRequest request(upload_session_url);
1230  request.set_multiple_options(std::forward<Options>(options)...);
1231  return raw_client_->DeleteResumableUpload(request).status();
1232  }
1233 
1234  /**
1235  * Downloads a Cloud Storage object to a file.
1236  *
1237  * @param bucket_name the name of the bucket that contains the object.
1238  * @param object_name the name of the object to be downloaded.
1239  * @param file_name the name of the destination file that will have the object
1240  * media.
1241  * @param options a list of optional query parameters and/or request headers.
1242  * Valid types for this operation include `IfGenerationMatch`,
1243  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1244  * `IfMetagenerationNotMatch`, `Generation`, `ReadFromOffset`, `ReadRange`,
1245  * and `UserProject`.
1246  *
1247  * @par Idempotency
1248  * This is a read-only operation and is always idempotent.
1249  *
1250  * @par Example
1251  * @snippet storage_object_file_transfer_samples.cc download file
1252  */
1253  template <typename... Options>
1254  Status DownloadToFile(std::string const& bucket_name,
1255  std::string const& object_name,
1256  std::string const& file_name, Options&&... options) {
1257  google::cloud::internal::OptionsSpan const span(
1258  SpanOptions(std::forward<Options>(options)...));
1259  internal::ReadObjectRangeRequest request(bucket_name, object_name);
1260  request.set_multiple_options(std::forward<Options>(options)...);
1261  return DownloadFileImpl(request, file_name);
1262  }
1263 
1264  /**
1265  * Deletes an object.
1266  *
1267  * @param bucket_name the name of the bucket that contains the object.
1268  * @param object_name the name of the object to be deleted.
1269  * @param options a list of optional query parameters and/or request headers.
1270  * Valid types for this operation include `Generation`,
1271  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1272  * `IfMetagenerationNotMatch`, and `UserProject`.
1273  *
1274  * @par Idempotency
1275  * This operation is only idempotent if:
1276  * - restricted by pre-conditions, in this case, `IfGenerationMatch`
1277  * - or, if it applies to only one object version via `Generation`.
1278  *
1279  * @par Example
1280  * @snippet storage_object_samples.cc delete object
1281  */
1282  template <typename... Options>
1283  Status DeleteObject(std::string const& bucket_name,
1284  std::string const& object_name, Options&&... options) {
1285  google::cloud::internal::OptionsSpan const span(
1286  SpanOptions(std::forward<Options>(options)...));
1287  internal::DeleteObjectRequest request(bucket_name, object_name);
1288  request.set_multiple_options(std::forward<Options>(options)...);
1289  return raw_client_->DeleteObject(request).status();
1290  }
1291 
1292  /**
1293  * Updates the metadata in a Google Cloud Storage Object.
1294  *
1295  * @param bucket_name the name of the bucket that contains the object.
1296  * @param object_name the name of the object.
1297  * @param metadata the new metadata for the Object. Only the writeable fields
1298  * accepted by the `Objects: update` API are used, all other fields are
1299  * ignored. In particular, note that `bucket` and `name` are ignored in
1300  * favor of @p bucket_name and @p object_name.
1301  * @param options a list of optional query parameters and/or request headers.
1302  * Valid types for this operation include `Generation`, `EncryptionKey`,
1303  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1304  * `IfMetagenerationNotMatch`, `PredefinedAcl`, `Projection`, and
1305  * `UserProject`.
1306  *
1307  * @par Idempotency
1308  * This operation is only idempotent if restricted by pre-conditions, in this
1309  * case, `IfMetagenerationMatch`.
1310  *
1311  * @par Example
1312  * @snippet storage_object_samples.cc update object metadata
1313  */
1314  template <typename... Options>
1315  StatusOr<ObjectMetadata> UpdateObject(std::string bucket_name,
1316  std::string object_name,
1317  ObjectMetadata metadata,
1318  Options&&... options) {
1319  google::cloud::internal::OptionsSpan const span(
1320  SpanOptions(std::forward<Options>(options)...));
1321  internal::UpdateObjectRequest request(
1322  std::move(bucket_name), std::move(object_name), std::move(metadata));
1323  request.set_multiple_options(std::forward<Options>(options)...);
1324  return raw_client_->UpdateObject(request);
1325  }
1326 
1327  /**
1328  * Patches the metadata in a Google Cloud Storage Object.
1329  *
1330  * This function creates a patch request to change the writeable attributes in
1331  * @p original to the values in @p updated. Non-writeable attributes are
1332  * ignored, and attributes not present in @p updated are removed. Typically
1333  * this function is used after the application obtained a value with
1334  * `GetObjectMetadata` and has modified these parameters.
1335  *
1336  * @param bucket_name the bucket that contains the object to be updated.
1337  * @param object_name the object to be updated.
1338  * @param original the initial value of the object metadata.
1339  * @param updated the updated value for the object metadata.
1340  * @param options a list of optional query parameters and/or request headers.
1341  * Valid types for this operation include `Generation`, `EncryptionKey`,
1342  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1343  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
1344  * `Projection`, and `UserProject`.
1345  *
1346  * @par Idempotency
1347  * This operation is only idempotent if restricted by pre-conditions, in this
1348  * case, `IfMetagenerationMatch`.
1349  *
1350  * @par Example
1351  * @snippet storage_object_samples.cc patch object delete metadata
1352  */
1353  template <typename... Options>
1354  StatusOr<ObjectMetadata> PatchObject(std::string bucket_name,
1355  std::string object_name,
1356  ObjectMetadata const& original,
1357  ObjectMetadata const& updated,
1358  Options&&... options) {
1359  google::cloud::internal::OptionsSpan const span(
1360  SpanOptions(std::forward<Options>(options)...));
1361  internal::PatchObjectRequest request(
1362  std::move(bucket_name), std::move(object_name), original, updated);
1363  request.set_multiple_options(std::forward<Options>(options)...);
1364  return raw_client_->PatchObject(request);
1365  }
1366 
1367  /**
1368  * Patches the metadata in a Google Cloud Storage Object.
1369  *
1370  * This function creates a patch request based on the given @p builder.
1371  * Typically this function is used when the application needs to set an
1372  * object's metadata fields regardless of their previous value (i.e. when
1373  * calling GetObjectMetadata first is not necessary).
1374  *
1375  * @param bucket_name the bucket that contains the object to be updated.
1376  * @param object_name the object to be updated.
1377  * @param builder the set of updates to perform in the Object metadata.
1378  * @param options a list of optional query parameters and/or request headers.
1379  * Valid types for this operation include `Generation`, `EncryptionKey`,
1380  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1381  * `IfMetagenerationNotMatch`, `PredefinedAcl`, `EncryptionKey`,
1382  * `Projection`, and `UserProject`.
1383  *
1384  * @par Idempotency
1385  * This operation is only idempotent if restricted by pre-conditions, in this
1386  * case, `IfMetagenerationMatch`.
1387  *
1388  * @par Example
1389  * @snippet storage_object_samples.cc patch object content type
1390  */
1391  template <typename... Options>
1393  std::string bucket_name, std::string object_name,
1394  ObjectMetadataPatchBuilder const& builder, Options&&... options) {
1395  google::cloud::internal::OptionsSpan const span(
1396  SpanOptions(std::forward<Options>(options)...));
1397  internal::PatchObjectRequest request(std::move(bucket_name),
1398  std::move(object_name), builder);
1399  request.set_multiple_options(std::forward<Options>(options)...);
1400  return raw_client_->PatchObject(request);
1401  }
1402 
1403  /**
1404  * Composes existing objects into a new object in the same bucket.
1405  *
1406  * @param bucket_name the name of the bucket used for source object and
1407  * destination object.
1408  * @param source_objects objects used to compose `destination_object_name`.
1409  * @param destination_object_name the composed object name.
1410  * @param options a list of optional query parameters and/or request headers.
1411  * Valid types for this operation include
1412  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1413  * `IfMetagenerationMatch`, `KmsKeyName`, `UserProject`, and
1414  * `WithObjectMetadata`.
1415  *
1416  * @par Idempotency
1417  * This operation is only idempotent if restricted by pre-conditions, in this
1418  * case, `IfGenerationMatch`.
1419  *
1420  * @par Example
1421  * @snippet storage_object_samples.cc compose object
1422  *
1423  * @par Example: using encrypted objects with CSEK
1424  * @snippet storage_object_csek_samples.cc compose object csek
1425  */
1426  template <typename... Options>
1428  std::string bucket_name, std::vector<ComposeSourceObject> source_objects,
1429  std::string destination_object_name, Options&&... options) {
1430  google::cloud::internal::OptionsSpan const span(
1431  SpanOptions(std::forward<Options>(options)...));
1432  internal::ComposeObjectRequest request(std::move(bucket_name),
1433  std::move(source_objects),
1434  std::move(destination_object_name));
1435  request.set_multiple_options(std::forward<Options>(options)...);
1436  return raw_client_->ComposeObject(request);
1437  }
1438 
1439  /**
1440  * Creates an `ObjectRewriter` to copy the source object.
1441  *
1442  * Applications use this function to reliably copy objects across [location
1443  * boundaries](https://cloud.google.com/storage/docs/locations), and to
1444  * rewrite objects with different encryption keys. The operation returns a
1445  * `ObjectRewriter`, which the application can use to initiate the copy and to
1446  * iterate if the copy requires more than one call to complete.
1447  *
1448  * @note Application developers should be aware that rewriting large objects
1449  * may take multiple hours. Multiple calls to `ObjectRewriter::Iterate()`
1450  * may be required to completely rewrite an object.
1451  *
1452  * @param source_bucket_name the name of the bucket containing the source
1453  * object.
1454  * @param source_object_name the name of the source object.
1455  * @param destination_bucket_name where the destination object will be
1456  * located.
1457  * @param destination_object_name what to name the destination object.
1458  * @param options a list of optional query parameters and/or request headers.
1459  * Valid types for this operation include `DestinationKmsKeyName`,
1460  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1461  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1462  * `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1463  * `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1464  * `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1465  * `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1466  *
1467  * @par Idempotency
1468  * This operation is only idempotent if restricted by pre-conditions, in this
1469  * case, `IfGenerationMatch`.
1470  *
1471  * @par Example
1472  * @snippet storage_object_rewrite_samples.cc rewrite object non blocking
1473  *
1474  * @par Example
1475  * @snippet storage_object_rewrite_samples.cc rewrite object resume
1476  */
1477  template <typename... Options>
1478  ObjectRewriter RewriteObject(std::string source_bucket_name,
1479  std::string source_object_name,
1480  std::string destination_bucket_name,
1481  std::string destination_object_name,
1482  Options&&... options) {
1483  return ResumeRewriteObject(
1484  std::move(source_bucket_name), std::move(source_object_name),
1485  std::move(destination_bucket_name), std::move(destination_object_name),
1486  std::string{}, std::forward<Options>(options)...);
1487  }
1488 
1489  /**
1490  * Creates an `ObjectRewriter` to resume a previously created rewrite.
1491  *
1492  * Applications use this function to resume a rewrite operation, possibly
1493  * created with `RewriteObject()`. Rewrite can reliably copy objects across
1494  * location boundaries, and can rewrite objects with different encryption
1495  * keys. For large objects this operation can take a long time, thus
1496  * applications should consider checkpointing the rewrite token (accessible in
1497  * the `ObjectRewriter`) and restarting the operation in the event the program
1498  * is terminated.
1499  *
1500  * @note Application developers should be aware that rewriting large objects
1501  * may take multiple hours. Multiple calls to `ObjectRewriter::Iterate()`
1502  * may be required to completely rewrite an object.
1503  *
1504  * @param source_bucket_name the name of the bucket containing the source
1505  * object.
1506  * @param source_object_name the name of the source object.
1507  * @param destination_bucket_name where the destination object will be
1508  * located.
1509  * @param destination_object_name what to name the destination object.
1510  * @param rewrite_token the token from a previous successful rewrite
1511  * iteration. Can be the empty string, in which case this starts a new
1512  * rewrite operation.
1513  * @param options a list of optional query parameters and/or request headers.
1514  * Valid types for this operation include `DestinationKmsKeyName`,
1515  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1516  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1517  * `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1518  * `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1519  * `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1520  * `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1521  *
1522  * @par Idempotency
1523  * This operation is only idempotent if restricted by pre-conditions, in this
1524  * case, `IfGenerationMatch`.
1525  *
1526  * @par Example
1527  * @snippet storage_object_rewrite_samples.cc rewrite object resume
1528  */
1529  template <typename... Options>
1530  ObjectRewriter ResumeRewriteObject(std::string source_bucket_name,
1531  std::string source_object_name,
1532  std::string destination_bucket_name,
1533  std::string destination_object_name,
1534  std::string rewrite_token,
1535  Options&&... options) {
1536  google::cloud::internal::OptionsSpan const span(
1537  SpanOptions(std::forward<Options>(options)...));
1538  internal::RewriteObjectRequest request(
1539  std::move(source_bucket_name), std::move(source_object_name),
1540  std::move(destination_bucket_name), std::move(destination_object_name),
1541  std::move(rewrite_token));
1542  request.set_multiple_options(std::forward<Options>(options)...);
1543  return ObjectRewriter(raw_client_, std::move(request));
1544  }
1545 
1546  /**
1547  * Rewrites the object, blocking until the rewrite completes, and returns the
1548  * resulting `ObjectMetadata`.
1549  *
1550  * Applications use this function to reliably copy objects across [location
1551  * boundaries](https://cloud.google.com/storage/docs/locations), and to
1552  * rewrite objects with different encryption keys. The operation blocks until
1553  * the rewrite completes, and returns the resulting `ObjectMetadata`.
1554  *
1555  * @note Application developers should be aware that rewriting large objects
1556  * may take multiple hours. In such cases the application should consider
1557  * using `RewriteObject()` or `ResumeRewriteObject()`.
1558  *
1559  * @param source_bucket_name the name of the bucket containing the source
1560  * object.
1561  * @param source_object_name the name of the source object.
1562  * @param destination_bucket_name where the destination object will be
1563  * located.
1564  * @param destination_object_name what to name the destination object.
1565  * @param options a list of optional query parameters and/or request headers.
1566  * Valid types for this operation include `DestinationKmsKeyName`,
1567  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1568  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1569  * `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1570  * `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1571  * `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1572  * `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1573  *
1574  * @return The metadata of the newly created object.
1575  *
1576  * @par Idempotency
1577  * This operation is only idempotent if restricted by pre-conditions, in this
1578  * case, `IfGenerationMatch`.
1579  *
1580  * @par Example
1581  * @snippet storage_object_rewrite_samples.cc rewrite object
1582  *
1583  * @par Example: using rewrite object to rotate the encryption key
1584  * @snippet storage_object_csek_samples.cc rotate encryption key
1585  *
1586  * @par Example: using rewrite object to rename an object
1587  * @snippet storage_object_rewrite_samples.cc rename object
1588  */
1589  template <typename... Options>
1591  std::string source_bucket_name, std::string source_object_name,
1592  std::string destination_bucket_name, std::string destination_object_name,
1593  Options&&... options) {
1594  return ResumeRewriteObject(std::move(source_bucket_name),
1595  std::move(source_object_name),
1596  std::move(destination_bucket_name),
1597  std::move(destination_object_name),
1598  std::string{}, std::forward<Options>(options)...)
1599  .Result();
1600  }
1601  ///@}
1602 
1603  /**
1604  * @name Bucket Access Control List operations.
1605  *
1606  * You can control who has access to your GCS buckets and objects as
1607  * well as what level of access they have.
1608  *
1609  * @note In most cases, you should use IAM permissions instead of ACLs to
1610  * control access to buckets.
1611  *
1612  * @note All buckets are owned by the project owners group. Project owners
1613  * are granted `OWNER` permissions to all buckets inside their project.
1614  * Bucket and object ownership cannot be changed by modifying ACLs.
1615  *
1616  * @note When you apply a new ACL to a bucket, GCS adds `OWNER` permission to
1617  * the bucket if you omit the grants. You cannot remove the project owners
1618  * group from a bucket ACL. Attempts to do so will appear to succeed, but
1619  * the service will add the project owners group into the new ACL before
1620  * applying it.
1621  *
1622  * @see https://cloud.google.com/storage/docs/access-control/ for more
1623  * information about access control in GCS.
1624  *
1625  * @see
1626  * https://cloud.google.com/storage/docs/access-control/lists#defaultbuckets
1627  * for more details about the default owners for a bucket.
1628  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1629  * the format of the @p entity parameters.
1630  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1631  * for the format of the @p role parameters.
1632  */
1633  ///@{
1634  /**
1635  * Retrieves the list of `BucketAccessControl` items for a bucket.
1636  *
1637  * @param bucket_name the name of the bucket.
1638  * @param options a list of optional query parameters and/or request headers.
1639  * Valid types for this operation include `UserProject`.
1640  *
1641  * @par Idempotency
1642  * This is a read-only operation and is always idempotent.
1643  *
1644  * @par Example
1645  * @snippet storage_bucket_acl_samples.cc list bucket acl
1646  */
1647  template <typename... Options>
1648  StatusOr<std::vector<BucketAccessControl>> ListBucketAcl(
1649  std::string const& bucket_name, Options&&... options) {
1650  google::cloud::internal::OptionsSpan const span(
1651  SpanOptions(std::forward<Options>(options)...));
1652  internal::ListBucketAclRequest request(bucket_name);
1653  request.set_multiple_options(std::forward<Options>(options)...);
1654  auto items = raw_client_->ListBucketAcl(request);
1655  if (!items) {
1656  return std::move(items).status();
1657  }
1658  return std::move(items.value().items);
1659  }
1660 
1661  /**
1662  * Creates a new entry in a bucket ACL.
1663  *
1664  * @param bucket_name the name of the bucket.
1665  * @param entity the name of the entity added to the ACL.
1666  * @param role the role of the entity.
1667  * @param options a list of optional query parameters and/or request headers.
1668  * Valid types for this operation include `UserProject`.
1669  *
1670  * @par Idempotency
1671  * This operation is only idempotent if restricted by pre-conditions. There
1672  * are no pre-conditions for this operation that can make it idempotent.
1673  *
1674  * @par Example
1675  * @snippet storage_bucket_acl_samples.cc create bucket acl
1676  *
1677  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1678  * the format of the @p entity parameter.
1679  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1680  * for the format of the @p role parameter.
1681  */
1682  template <typename... Options>
1683  StatusOr<BucketAccessControl> CreateBucketAcl(std::string const& bucket_name,
1684  std::string const& entity,
1685  std::string const& role,
1686  Options&&... options) {
1687  google::cloud::internal::OptionsSpan const span(
1688  SpanOptions(std::forward<Options>(options)...));
1689  internal::CreateBucketAclRequest request(bucket_name, entity, role);
1690  request.set_multiple_options(std::forward<Options>(options)...);
1691  return raw_client_->CreateBucketAcl(request);
1692  }
1693 
1694  /**
1695  * Deletes an entry from a bucket ACL.
1696  *
1697  * @param bucket_name the name of the bucket.
1698  * @param entity the name of the entity added to the ACL.
1699  * @param options a list of optional query parameters and/or request headers.
1700  * Valid types for this operation include `UserProject`.
1701  *
1702  * @par Idempotency
1703  * This operation is only idempotent if restricted by pre-conditions. There
1704  * are no pre-conditions for this operation that can make it idempotent.
1705  *
1706  * @par Example
1707  * @snippet storage_bucket_acl_samples.cc delete bucket acl
1708  *
1709  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1710  * the format of the @p entity parameter.
1711  */
1712  template <typename... Options>
1713  Status DeleteBucketAcl(std::string const& bucket_name,
1714  std::string const& entity, Options&&... options) {
1715  google::cloud::internal::OptionsSpan const span(
1716  SpanOptions(std::forward<Options>(options)...));
1717  internal::DeleteBucketAclRequest request(bucket_name, entity);
1718  request.set_multiple_options(std::forward<Options>(options)...);
1719  return raw_client_->DeleteBucketAcl(request).status();
1720  }
1721 
1722  /**
1723  * Gets the value of an existing bucket ACL.
1724  *
1725  * @param bucket_name the name of the bucket to query.
1726  * @param entity the name of the entity to query.
1727  * @param options a list of optional query parameters and/or request headers.
1728  * Valid types for this operation include `UserProject`.
1729  *
1730  * @par Idempotency
1731  * This is a read-only operation and is always idempotent.
1732  *
1733  * @par Example
1734  * @snippet storage_bucket_acl_samples.cc get bucket acl
1735  *
1736  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1737  * the format of the @p entity parameter.
1738  */
1739  template <typename... Options>
1740  StatusOr<BucketAccessControl> GetBucketAcl(std::string const& bucket_name,
1741  std::string const& entity,
1742  Options&&... options) {
1743  google::cloud::internal::OptionsSpan const span(
1744  SpanOptions(std::forward<Options>(options)...));
1745  internal::GetBucketAclRequest request(bucket_name, entity);
1746  request.set_multiple_options(std::forward<Options>(options)...);
1747  return raw_client_->GetBucketAcl(request);
1748  }
1749 
1750  /**
1751  * Updates the value of an existing bucket ACL.
1752  *
1753  * @note
1754  * For changing BucketAccessControl, the Patch and Update APIs basically offer
1755  * the same functionality. The only field that can be modified by either API
1756  * is `role`, and it may only be set to a new value (it cannot be removed).
1757  * The API is offered for consistency with the other resource types where
1758  * Patch and Update APIs have different semantics.
1759  *
1760  * @param bucket_name the name of the bucket.
1761  * @param acl the new ACL value. Note that only the writable values of the ACL
1762  * will be modified by the server.
1763  * @param options a list of optional query parameters and/or request headers.
1764  * Valid types for this operation include `UserProject`.
1765  *
1766  * @par Idempotency
1767  * This operation is only idempotent if restricted by pre-conditions. There
1768  * are no pre-conditions for this operation that can make it idempotent.
1769  *
1770  * @par Example
1771  * @snippet storage_bucket_acl_samples.cc update bucket acl
1772  *
1773  * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1774  * for additional details on what fields are writeable.
1775  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1776  * the format of the @p entity parameter.
1777  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1778  * for the format of the @p role parameter.
1779  */
1780  template <typename... Options>
1781  StatusOr<BucketAccessControl> UpdateBucketAcl(std::string const& bucket_name,
1782  BucketAccessControl const& acl,
1783  Options&&... options) {
1784  google::cloud::internal::OptionsSpan const span(
1785  SpanOptions(std::forward<Options>(options)...));
1786  internal::UpdateBucketAclRequest request(bucket_name, acl.entity(),
1787  acl.role());
1788  request.set_multiple_options(std::forward<Options>(options)...);
1789  return raw_client_->UpdateBucketAcl(request);
1790  }
1791 
1792  /**
1793  * Patches the value of an existing bucket ACL.
1794  *
1795  * Computes the delta between a previous value for an BucketAccessControl and
1796  * the new value for an BucketAccessControl and apply that delta.
1797  *
1798  * @note
1799  * For changing BucketAccessControl, the Patch and Update APIs basically offer
1800  * the same functionality. The only field that can be modified by either API
1801  * is `role`, and it may only be set to a new value (it cannot be removed).
1802  * The API is offered for consistency with the other resource types where
1803  * Patch and Update APIs have different semantics.
1804  *
1805  * @param bucket_name the name of the bucket.
1806  * @param entity the identifier for the user, group, service account, or
1807  * predefined set of actors holding the permission.
1808  * @param original_acl the original ACL value.
1809  * @param new_acl the new ACL value. Note that only changes on writeable
1810  * fields will be accepted by the server.
1811  * @param options a list of optional query parameters and/or request headers.
1812  * Valid types for this operation include `UserProject`, and the standard
1813  * options available to all operations.
1814  *
1815  * @par Idempotency
1816  * This operation is only idempotent if restricted by pre-conditions. There
1817  * are no pre-conditions for this operation that can make it idempotent.
1818  *
1819  * @par Example
1820  * @snippet storage_bucket_acl_samples.cc patch bucket acl
1821  *
1822  * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1823  * for additional details on what fields are writeable.
1824  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1825  * the format of the @p entity parameters.
1826  */
1827  template <typename... Options>
1829  std::string const& bucket_name, std::string const& entity,
1830  BucketAccessControl const& original_acl,
1831  BucketAccessControl const& new_acl, Options&&... options) {
1832  google::cloud::internal::OptionsSpan const span(
1833  SpanOptions(std::forward<Options>(options)...));
1834  internal::PatchBucketAclRequest request(bucket_name, entity, original_acl,
1835  new_acl);
1836  request.set_multiple_options(std::forward<Options>(options)...);
1837  return raw_client_->PatchBucketAcl(request);
1838  }
1839 
1840  /**
1841  * Patches the value of an existing bucket ACL.
1842  *
1843  * This API allows the application to patch an BucketAccessControl without
1844  * having to read the current value.
1845  *
1846  * @note
1847  * For changing BucketAccessControl, the Patch and Update APIs basically offer
1848  * the same functionality. The only field that can be modified by either API
1849  * is `role`, and it may only be set to a new value (it cannot be removed).
1850  * The API is offered for consistency with the other resource types where
1851  * Patch and Update APIs have different semantics.
1852  *
1853  * @param bucket_name the name of the bucket.
1854  * @param entity the identifier for the user, group, service account, or
1855  * predefined set of actors holding the permission.
1856  * @param builder a builder ready to create the patch.
1857  * @param options a list of optional query parameters and/or request
1858  * headers. Valid types for this operation include `Generation`,
1859  * `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
1860  *
1861  * @par Idempotency
1862  * This operation is only idempotent if restricted by pre-conditions. There
1863  * are no pre-conditions for this operation that can make it idempotent.
1864  *
1865  * @par Example
1866  * @snippet storage_bucket_acl_samples.cc patch bucket acl no-read
1867  *
1868  * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1869  * for additional details on what fields are writeable.
1870  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1871  * the format of the @p entity parameters.
1872  */
1873  template <typename... Options>
1875  std::string const& bucket_name, std::string const& entity,
1876  BucketAccessControlPatchBuilder const& builder, Options&&... options) {
1877  google::cloud::internal::OptionsSpan const span(
1878  SpanOptions(std::forward<Options>(options)...));
1879  internal::PatchBucketAclRequest request(bucket_name, entity, builder);
1880  request.set_multiple_options(std::forward<Options>(options)...);
1881  return raw_client_->PatchBucketAcl(request);
1882  }
1883  ///@}
1884 
1885  /**
1886  * @name Object Access Control List operations.
1887  *
1888  * You can control who has access to your GCS buckets and objects as
1889  * well as what level of access they have.
1890  *
1891  * @note When you upload (create) an object the entity that uploads the object
1892  * is listed as the object owner. This can be a user or a service account,
1893  * depending on what credentials are used to authenticate with GCS.
1894  * Object ownership cannot be changed by modifying ACLs. You can change
1895  * object ownership only by overwriting the object while authenticated as
1896  * the desired owner.
1897  *
1898  * @note When you apply a new ACL to an object, GCS adds `OWNER` permission to
1899  * the object if you omit the grants.
1900  *
1901  * @see https://cloud.google.com/storage/docs/access-control/ for more
1902  * information about access control in GCS.
1903  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1904  * the format of the @p entity parameters.
1905  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1906  * for the format of the @p role parameters.
1907  */
1908  ///@{
1909  /**
1910  * Retrieves the list of ObjectAccessControl items for an object.
1911  *
1912  * @param bucket_name the name of the bucket that contains the object.
1913  * @param object_name the name of the object to be deleted.
1914  * @param options a list of optional query parameters and/or request headers.
1915  * Valid types for this operation include `Generation`, and `UserProject`.
1916  *
1917  * @par Idempotency
1918  * This is a read-only operation and is always idempotent.
1919  *
1920  * @par Example
1921  * @snippet storage_object_acl_samples.cc list object acl
1922  */
1923  template <typename... Options>
1924  StatusOr<std::vector<ObjectAccessControl>> ListObjectAcl(
1925  std::string const& bucket_name, std::string const& object_name,
1926  Options&&... options) {
1927  google::cloud::internal::OptionsSpan const span(
1928  SpanOptions(std::forward<Options>(options)...));
1929  internal::ListObjectAclRequest request(bucket_name, object_name);
1930  request.set_multiple_options(std::forward<Options>(options)...);
1931  auto result = raw_client_->ListObjectAcl(request);
1932  if (!result) {
1933  return std::move(result).status();
1934  }
1935  return std::move(result.value().items);
1936  }
1937 
1938  /**
1939  * Creates a new entry in the object ACL.
1940  *
1941  * @param bucket_name the name of the bucket that contains the object.
1942  * @param object_name the name of the object.
1943  * @param entity the name of the entity added to the ACL.
1944  * @param role the role of the entity.
1945  * @param options a list of optional query parameters and/or request headers.
1946  * Valid types for this operation include `Generation`, and `UserProject`.
1947  *
1948  * @par Idempotency
1949  * This operation is only idempotent if restricted by pre-conditions. There
1950  * are no pre-conditions for this operation that can make it idempotent.
1951  *
1952  * @par Example
1953  * @snippet storage_object_acl_samples.cc create object acl
1954  *
1955  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1956  * the format of the @p entity parameter.
1957  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1958  * for the format of the @p role parameter.
1959  */
1960  template <typename... Options>
1961  StatusOr<ObjectAccessControl> CreateObjectAcl(std::string const& bucket_name,
1962  std::string const& object_name,
1963  std::string const& entity,
1964  std::string const& role,
1965  Options&&... options) {
1966  google::cloud::internal::OptionsSpan const span(
1967  SpanOptions(std::forward<Options>(options)...));
1968  internal::CreateObjectAclRequest request(bucket_name, object_name, entity,
1969  role);
1970  request.set_multiple_options(std::forward<Options>(options)...);
1971  return raw_client_->CreateObjectAcl(request);
1972  }
1973 
1974  /**
1975  * Deletes one access control entry in one object.
1976  *
1977  * @param bucket_name the name of the bucket that contains the object.
1978  * @param object_name the name of the object to be deleted.
1979  * @param entity the name of the entity (user, team, group) to be removed from
1980  * the Object's ACL.
1981  * @param options a list of optional query parameters and/or request headers.
1982  * Valid types for this operation include `Generation`, and `UserProject`.
1983  *
1984  * @par Idempotency
1985  * This operation is only idempotent if restricted by pre-conditions. There
1986  * are no pre-conditions for this operation that can make it idempotent.
1987  *
1988  * @par Example
1989  * @snippet storage_object_acl_samples.cc delete object acl
1990  *
1991  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1992  * the format of the @p entity parameters.
1993  */
1994  template <typename... Options>
1995  Status DeleteObjectAcl(std::string const& bucket_name,
1996  std::string const& object_name,
1997  std::string const& entity, Options&&... options) {
1998  google::cloud::internal::OptionsSpan const span(
1999  SpanOptions(std::forward<Options>(options)...));
2000  internal::DeleteObjectAclRequest request(bucket_name, object_name, entity);
2001  request.set_multiple_options(std::forward<Options>(options)...);
2002  return raw_client_->DeleteObjectAcl(request).status();
2003  }
2004 
2005  /**
2006  * Gets the value of an existing object ACL.
2007  *
2008  * @param bucket_name the name of the bucket that contains the object.
2009  * @param object_name the name of the object.
2010  * @param entity the name of the entity added to the ACL.
2011  * @param options a list of optional query parameters and/or request headers.
2012  * Valid types for this operation include `Generation`, and `UserProject`.
2013  *
2014  * @par Idempotency
2015  * This is a read-only operation and is always idempotent.
2016  *
2017  * @par Example
2018  * @snippet storage_object_acl_samples.cc print file acl for user
2019  *
2020  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2021  * the format of the @p entity parameters.
2022  */
2023  template <typename... Options>
2024  StatusOr<ObjectAccessControl> GetObjectAcl(std::string const& bucket_name,
2025  std::string const& object_name,
2026  std::string const& entity,
2027  Options&&... options) {
2028  google::cloud::internal::OptionsSpan const span(
2029  SpanOptions(std::forward<Options>(options)...));
2030  internal::GetObjectAclRequest request(bucket_name, object_name, entity);
2031  request.set_multiple_options(std::forward<Options>(options)...);
2032  return raw_client_->GetObjectAcl(request);
2033  }
2034 
2035  /**
2036  * Updates the value of an existing object ACL.
2037  *
2038  * @note
2039  * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2040  * the same functionality. The only field that can be modified by either API
2041  * is `role`, and it may only be set to a new value (it cannot be removed).
2042  * The API is offered for consistency with the other resource types where
2043  * Patch and Update APIs have different semantics.
2044  *
2045  * @param bucket_name the name of the bucket that contains the object.
2046  * @param object_name the name of the object.
2047  * @param acl the new ACL value. Note that only the writable values of the ACL
2048  * will be modified by the server.
2049  * @param options a list of optional query parameters and/or request
2050  * Valid types for this operation include `Generation`, and `UserProject`.
2051  *
2052  * @par Idempotency
2053  * This operation is only idempotent if restricted by pre-conditions. There
2054  * are no pre-conditions for this operation that can make it idempotent.
2055  *
2056  * @par Example
2057  * @snippet storage_object_acl_samples.cc update object acl
2058  *
2059  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2060  * the format of the @p entity parameters.
2061  * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2062  * for additional details on what fields are writeable.
2063  */
2064  template <typename... Options>
2065  StatusOr<ObjectAccessControl> UpdateObjectAcl(std::string const& bucket_name,
2066  std::string const& object_name,
2067  ObjectAccessControl const& acl,
2068  Options&&... options) {
2069  google::cloud::internal::OptionsSpan const span(
2070  SpanOptions(std::forward<Options>(options)...));
2071  internal::UpdateObjectAclRequest request(bucket_name, object_name,
2072  acl.entity(), acl.role());
2073  request.set_multiple_options(std::forward<Options>(options)...);
2074  return raw_client_->UpdateObjectAcl(request);
2075  }
2076 
2077  /**
2078  * Patches the value of an existing object ACL.
2079  *
2080  * Compute the delta between a previous value for an ObjectAccessControl and
2081  * the new value for an ObjectAccessControl and apply that delta.
2082  *
2083  * @note
2084  * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2085  * the same functionality. The only field that can be modified by either API
2086  * is `role`, and it may only be set to a new value (it cannot be removed).
2087  * The API is offered for consistency with the other resource types where
2088  * Patch and Update APIs have different semantics.
2089  *
2090  * @param bucket_name the name of the bucket that contains the object.
2091  * @param object_name the name of the object.
2092  * @param entity the identifier for the user, group, service account, or
2093  * predefined set of actors holding the permission.
2094  * @param original_acl the original ACL value.
2095  * @param new_acl the new ACL value. Note that only changes on writeable
2096  * fields will be accepted by the server.
2097  * @param options a list of optional query parameters and/or request
2098  * headers. Valid types for this operation include `Generation`,
2099  * `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
2100  *
2101  * @par Idempotency
2102  * This operation is only idempotent if restricted by pre-conditions. There
2103  * are no pre-conditions for this operation that can make it idempotent.
2104  *
2105  * @par Example
2106  * @snippet storage_object_acl_samples.cc patch object acl
2107  *
2108  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2109  * the format of the @p entity parameters.
2110  * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2111  * for additional details on what fields are writeable.
2112  */
2113  template <typename... Options>
2115  std::string const& bucket_name, std::string const& object_name,
2116  std::string const& entity, ObjectAccessControl const& original_acl,
2117  ObjectAccessControl const& new_acl, Options&&... options) {
2118  google::cloud::internal::OptionsSpan const span(
2119  SpanOptions(std::forward<Options>(options)...));
2120  internal::PatchObjectAclRequest request(bucket_name, object_name, entity,
2121  original_acl, new_acl);
2122  request.set_multiple_options(std::forward<Options>(options)...);
2123  return raw_client_->PatchObjectAcl(request);
2124  }
2125 
2126  /**
2127  * Patches the value of an existing object ACL.
2128  *
2129  * This API allows the application to patch an ObjectAccessControl without
2130  * having to read the current value.
2131  *
2132  * @note
2133  * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2134  * the same functionality. The only field that can be modified by either API
2135  * is `role`, and it may only be set to a new value (it cannot be removed).
2136  * The API is offered for consistency with the other resource types where
2137  * Patch and Update APIs have different semantics.
2138  *
2139  * @param bucket_name the name of the bucket that contains the object.
2140  * @param object_name the name of the object.
2141  * @param entity the identifier for the user, group, service account, or
2142  * predefined set of actors holding the permission.
2143  * @param builder a builder ready to create the patch.
2144  * @param options a list of optional query parameters and/or request
2145  * headers. Valid types for this operation include `Generation`,
2146  * `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
2147  *
2148  * @par Idempotency
2149  * This operation is only idempotent if restricted by pre-conditions. There
2150  * are no pre-conditions for this operation that can make it idempotent.
2151  *
2152  * @par Example
2153  * @snippet storage_object_acl_samples.cc patch object acl no-read
2154  *
2155  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2156  * the format of the @p entity parameters.
2157  * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2158  * for additional details on what fields are writeable.
2159  */
2160  template <typename... Options>
2162  std::string const& bucket_name, std::string const& object_name,
2163  std::string const& entity, ObjectAccessControlPatchBuilder const& builder,
2164  Options&&... options) {
2165  google::cloud::internal::OptionsSpan const span(
2166  SpanOptions(std::forward<Options>(options)...));
2167  internal::PatchObjectAclRequest request(bucket_name, object_name, entity,
2168  builder);
2169  request.set_multiple_options(std::forward<Options>(options)...);
2170  return raw_client_->PatchObjectAcl(request);
2171  }
2172  ///@}
2173 
2174  /**
2175  * @name Bucket Default Object Access Control List operations.
2176  *
2177  * When you upload an object to GCS without specifying an ACL, the object is
2178  * created with the Default Object ACL for its bucket. These operations are
2179  * used to query and modify the Default Object ACL of a bucket.
2180  *
2181  * @see
2182  * https://cloud.google.com/storage/docs/access-control/lists#defaultobjects
2183  * for more information on default object ACLs.
2184  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2185  * the format of the @p entity parameters.
2186  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2187  * for the format of the @p role parameters.
2188  */
2189  ///@{
2190  /**
2191  * Retrieves the default object ACL for a bucket as a vector of
2192  * `ObjectAccessControl` items.
2193  *
2194  * The default object ACL sets the ACL for any object created in the bucket,
2195  * unless a different ACL is specified when the object is created.
2196  *
2197  * @param bucket_name the name of the bucket.
2198  * @param options a list of optional query parameters and/or request headers.
2199  * Valid types for this operation include `IfMetagenerationMatch`,
2200  * `IfMetagenerationNotMatch` and `UserProject`.
2201  *
2202  * @par Idempotency
2203  * This is a read-only operation and is always idempotent.
2204  *
2205  * @par Example
2206  * @snippet storage_default_object_acl_samples.cc list default object acl
2207  *
2208  * @see
2209  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2210  */
2211  template <typename... Options>
2213  std::string const& bucket_name, Options&&... options) {
2214  google::cloud::internal::OptionsSpan const span(
2215  SpanOptions(std::forward<Options>(options)...));
2216  internal::ListDefaultObjectAclRequest request(bucket_name);
2217  request.set_multiple_options(std::forward<Options>(options)...);
2218  auto response = raw_client_->ListDefaultObjectAcl(request);
2219  if (!response) {
2220  return std::move(response).status();
2221  }
2222  return std::move(response.value().items);
2223  }
2224 
2225  /**
2226  * Creates a new entry in the default object ACL for a bucket.
2227  *
2228  * The default object ACL sets the ACL for any object created in the bucket,
2229  * unless a different ACL is specified when the object is created.
2230  *
2231  * @param bucket_name the name of the bucket.
2232  * @param entity the name of the entity added to the ACL.
2233  * @param role the role of the entity.
2234  * @param options a list of optional query parameters and/or request headers.
2235  * Valid types for this operation include `UserProject`.
2236  *
2237  * @par Idempotency
2238  * This operation is only idempotent if restricted by pre-conditions. There
2239  * are no pre-conditions for this operation that can make it idempotent.
2240  *
2241  * @par Example
2242  * @snippet storage_default_object_acl_samples.cc create default object acl
2243  *
2244  * @see
2245  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2246  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2247  * the format of the @p entity parameter.
2248  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2249  * for the format of the @p role parameter.
2250  */
2251  template <typename... Options>
2253  std::string const& bucket_name, std::string const& entity,
2254  std::string const& role, Options&&... options) {
2255  google::cloud::internal::OptionsSpan const span(
2256  SpanOptions(std::forward<Options>(options)...));
2257  internal::CreateDefaultObjectAclRequest request(bucket_name, entity, role);
2258  request.set_multiple_options(std::forward<Options>(options)...);
2259  return raw_client_->CreateDefaultObjectAcl(request);
2260  }
2261 
2262  /**
2263  * Deletes an entry from the default object ACL in a bucket.
2264  *
2265  * The default object ACL sets the ACL for any object created in the bucket,
2266  * unless a different ACL is specified when the object is created.
2267  *
2268  * @param bucket_name the name of the bucket.
2269  * @param entity the name of the entity added to the ACL.
2270  * @param options a list of optional query parameters and/or request headers.
2271  * Valid types for this operation include `UserProject`.
2272  *
2273  * @par Idempotency
2274  * This operation is only idempotent if restricted by pre-conditions. There
2275  * are no pre-conditions for this operation that can make it idempotent.
2276  *
2277  * @par Example
2278  * @snippet storage_default_object_acl_samples.cc delete default object acl
2279  *
2280  * @see
2281  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2282  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2283  * the format of the @p entity parameter.
2284  */
2285  template <typename... Options>
2286  Status DeleteDefaultObjectAcl(std::string const& bucket_name,
2287  std::string const& entity,
2288  Options&&... options) {
2289  google::cloud::internal::OptionsSpan const span(
2290  SpanOptions(std::forward<Options>(options)...));
2291  internal::DeleteDefaultObjectAclRequest request(bucket_name, entity);
2292  request.set_multiple_options(std::forward<Options>(options)...);
2293  return raw_client_->DeleteDefaultObjectAcl(request).status();
2294  }
2295 
2296  /**
2297  * Gets the value of a default object ACL in a bucket.
2298  *
2299  * The default object ACL sets the ACL for any object created in the bucket,
2300  * unless a different ACL is specified when the object is created.
2301  *
2302  * @param bucket_name the name of the bucket.
2303  * @param entity the name of the entity.
2304  * @param options a list of optional query parameters and/or request headers.
2305  * Valid types for this operation include `UserProject`.
2306  *
2307  * @par Idempotency
2308  * This is a read-only operation and is always idempotent.
2309  *
2310  * @par Example
2311  * @snippet storage_default_object_acl_samples.cc get default object acl
2312  *
2313  * @see
2314  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2315  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2316  * the format of the @p entity parameter.
2317  */
2318  template <typename... Options>
2320  std::string const& bucket_name, std::string const& entity,
2321  Options&&... options) {
2322  google::cloud::internal::OptionsSpan const span(
2323  SpanOptions(std::forward<Options>(options)...));
2324  internal::GetDefaultObjectAclRequest request(bucket_name, entity);
2325  request.set_multiple_options(std::forward<Options>(options)...);
2326  return raw_client_->GetDefaultObjectAcl(request);
2327  }
2328 
2329  /**
2330  * Updates the value of an existing default object ACL.
2331  *
2332  * The default object ACL sets the ACL for any object created in the bucket,
2333  * unless a different ACL is specified when the object is created.
2334  *
2335  * @note
2336  * For changing default object access controls, the Patch and Update APIs
2337  * basically offer the same functionality. The only field that can be modified
2338  * by either API is `role`, and it may only be set to a new value (it cannot
2339  * be removed). The API is offered for consistency with the other resource
2340  * types where Patch and Update APIs have different semantics.
2341  *
2342  * @param bucket_name the name of the bucket.
2343  * @param acl the new ACL value. Note that only the writable values of the ACL
2344  * will be modified by the server.
2345  * @param options a list of optional query parameters and/or request
2346  * Valid types for this operation include `UserProject`.
2347  *
2348  * @par Idempotency
2349  * This operation is only idempotent if restricted by pre-conditions. There
2350  * are no pre-conditions for this operation that can make it idempotent.
2351  *
2352  * @par Example
2353  * @snippet storage_default_object_acl_samples.cc update default object acl
2354  *
2355  * @see
2356  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2357  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2358  * the format of the @p entity parameter.
2359  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2360  * for the format of the @p role parameter.
2361  */
2362  template <typename... Options>
2364  std::string const& bucket_name, ObjectAccessControl const& acl,
2365  Options&&... options) {
2366  google::cloud::internal::OptionsSpan const span(
2367  SpanOptions(std::forward<Options>(options)...));
2368  internal::UpdateDefaultObjectAclRequest request(bucket_name, acl.entity(),
2369  acl.role());
2370  request.set_multiple_options(std::forward<Options>(options)...);
2371  return raw_client_->UpdateDefaultObjectAcl(request);
2372  }
2373 
2374  /**
2375  * Patches the value of an existing default object ACL.
2376  *
2377  * Compute the delta between a previous and new values for a default object
2378  * access control, and apply that delta.
2379  *
2380  * @note
2381  * For changing default object access controls, the Patch and Update APIs
2382  * basically offer the same functionality. The only field that can be modified
2383  * by either API is `role`, and it may only be set to a new value (it cannot
2384  * be removed). The API is offered for consistency with the other resource
2385  * types where Patch and Update APIs have different semantics.
2386  *
2387  * @param bucket_name the name of the bucket.
2388  * @param entity the identifier for the user, group, service account, or
2389  * predefined set of actors holding the permission.
2390  * @param original_acl the original ACL value.
2391  * @param new_acl the new ACL value. Note that only changes on writeable
2392  * fields will be accepted by the server.
2393  * @param options a list of optional query parameters and/or request
2394  * headers. Valid types for this operation include `UserProject`, as well
2395  * as the standard parameters, such as `IfMatchEtag`, and
2396  * `IfNoneMatchEtag`.
2397  *
2398  * @par Idempotency
2399  * This operation is only idempotent if restricted by pre-conditions. There
2400  * are no pre-conditions for this operation that can make it idempotent.
2401  *
2402  * @par Example
2403  * @snippet storage_default_object_acl_samples.cc patch default object acl
2404  *
2405  * @see
2406  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2407  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2408  * the format of the @p entity parameter.
2409  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2410  * for the format of the @p role parameter.
2411  */
2412  template <typename... Options>
2414  std::string const& bucket_name, std::string const& entity,
2415  ObjectAccessControl const& original_acl,
2416  ObjectAccessControl const& new_acl, Options&&... options) {
2417  google::cloud::internal::OptionsSpan const span(
2418  SpanOptions(std::forward<Options>(options)...));
2419  internal::PatchDefaultObjectAclRequest request(bucket_name, entity,
2420  original_acl, new_acl);
2421  request.set_multiple_options(std::forward<Options>(options)...);
2422  return raw_client_->PatchDefaultObjectAcl(request);
2423  }
2424 
2425  /**
2426  * Patches the value of an existing default object ACL.
2427  *
2428  * This API allows the application to patch an ObjectAccessControl without
2429  * having to read the current value.
2430  *
2431  * @note
2432  * For changing default object access controls, the Patch and Update APIs
2433  * basically offer the same functionality. The only field that can be modified
2434  * by either API is `role`, and it may only be set to a new value (it cannot
2435  * be removed). The API is offered for consistency with the other resource
2436  * types where Patch and Update APIs have different semantics.
2437  *
2438  * @param bucket_name the name of the bucket.
2439  * @param entity the identifier for the user, group, service account, or
2440  * predefined set of actors holding the permission.
2441  * @param builder a builder ready to create the patch.
2442  * @param options a list of optional query parameters and/or request
2443  * headers. Valid types for this operation include `UserProject`, as well
2444  * as the standard parameters, such as `IfMatchEtag`, and
2445  * `IfNoneMatchEtag`.
2446  *
2447  * @par Idempotency
2448  * This operation is only idempotent if restricted by pre-conditions. There
2449  * are no pre-conditions for this operation that can make it idempotent.
2450  *
2451  * @par Example
2452  * @snippet storage_default_object_acl_samples.cc patch default object acl
2453  * no-read
2454  *
2455  * @see
2456  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2457  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2458  * the format of the @p entity parameter.
2459  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2460  * for the format of the @p role parameter.
2461  */
2462  template <typename... Options>
2464  std::string const& bucket_name, std::string const& entity,
2465  ObjectAccessControlPatchBuilder const& builder, Options&&... options) {
2466  google::cloud::internal::OptionsSpan const span(
2467  SpanOptions(std::forward<Options>(options)...));
2468  internal::PatchDefaultObjectAclRequest request(bucket_name, entity,
2469  builder);
2470  request.set_multiple_options(std::forward<Options>(options)...);
2471  return raw_client_->PatchDefaultObjectAcl(request);
2472  }
2473  ///@}
2474 
2475  /**
2476  * @name Service account operations.
2477  *
2478  * Service accounts allow applications to authenticate and access GCP
2479  * resources and services. When acting on your behalf, GCS uses such a service
2480  * account. GCS creates one service account per project. These operations
2481  * allow you to query the GCS service account for a project.
2482  *
2483  * @see https://cloud.google.com/storage/docs/projects#service-accounts for
2484  * more information on service accounts.
2485  */
2486  ///@{
2487  /**
2488  * Gets the GCS service account for a given project.
2489  *
2490  * A service account is a special Google account that belongs to your
2491  * application, virtual machine, or to a Google service when acting on your
2492  * behalf. This API allows you to discover the GCS service account for the
2493  * @p project_id project.
2494  *
2495  * @param project_id the project to query.
2496  * @param options a list of optional query parameters and/or request headers.
2497  * Valid types for this operation include `UserProject`.
2498  *
2499  * @par Idempotency
2500  * This is a read-only operation and is always idempotent.
2501  *
2502  * @par Example
2503  * @snippet storage_service_account_samples.cc get service account for project
2504  *
2505  * @see https://cloud.google.com/iam/docs/service-accounts for general
2506  * information on Google Cloud Platform service accounts.
2507  */
2508  template <typename... Options>
2510  std::string const& project_id, Options&&... options) {
2511  google::cloud::internal::OptionsSpan const span(
2512  SpanOptions(std::forward<Options>(options)...));
2513  internal::GetProjectServiceAccountRequest request(project_id);
2514  request.set_multiple_options(std::forward<Options>(options)...);
2515  return raw_client_->GetServiceAccount(request);
2516  }
2517 
2518  /**
2519  * Gets the GCS service account for the default project.
2520  *
2521  * A service account is a special Google account that belongs to your
2522  * application, virtual machine, or to a Google service when acting on your
2523  * behalf. This API allows you to discover the GCS service account for the
2524  * default project associated with this object.
2525  *
2526  * The default project is required to be configured in the `ClientOptions`
2527  * used to construct this object. If the application does not set the project
2528  * id in the `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is
2529  * used. If neither the environment variable is set, nor a value is set
2530  * explicitly by the application, the server will reject the request and this
2531  * function will return the error status.
2532  *
2533  * @param options a list of optional query parameters and/or request headers.
2534  * Valid types for this operation include `UserProject`.
2535  *
2536  * @par Idempotency
2537  * This is a read-only operation and is always idempotent.
2538  *
2539  * @par Example
2540  * @snippet storage_service_account_samples.cc get service account
2541  *
2542  * @see https://cloud.google.com/iam/docs/service-accounts for general
2543  * information on Google Cloud Platform service accounts.
2544  */
2545  template <typename... Options>
2546  StatusOr<ServiceAccount> GetServiceAccount(Options&&... options) {
2547  google::cloud::internal::OptionsSpan const span(
2548  SpanOptions(std::forward<Options>(options)...));
2549  auto const& project_id = raw_client_->client_options().project_id();
2550  return GetServiceAccountForProject(project_id,
2551  std::forward<Options>(options)...);
2552  }
2553 
2554  /**
2555  * List the available HMAC keys.
2556  *
2557  * @warning This GCS feature is not GA, it is subject to change without
2558  * notice.
2559  *
2560  * @param options a list of optional query parameters and/or request headers.
2561  * In addition to the options common to all requests, this operation
2562  * accepts `Deleted` `MaxResults`, `OverrideDefaultProject`,
2563  * and `ServiceAccountFilter`.
2564  *
2565  * @return A range to iterate over the available HMAC keys.
2566  *
2567  * @par Idempotency
2568  * This is a read-only operation and is always idempotent.
2569  *
2570  * @par Example
2571  * @snippet storage_service_account_samples.cc list hmac keys
2572  *
2573  * @par Example
2574  * @snippet storage_service_account_samples.cc list hmac keys service account
2575  *
2576  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2577  * general information on using HMAC keys for Google Cloud Platform
2578  * service accounts authentication.
2579  *
2580  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2581  * for a detailed description on how to use the feature.
2582  */
2583  template <typename... Options>
2584  ListHmacKeysReader ListHmacKeys(Options&&... options) {
2585  google::cloud::internal::OptionsSpan const span(
2586  SpanOptions(std::forward<Options>(options)...));
2587  auto const& project_id = raw_client_->client_options().project_id();
2588  internal::ListHmacKeysRequest request(project_id);
2589  request.set_multiple_options(std::forward<Options>(options)...);
2590  auto& client = raw_client_;
2591  return google::cloud::internal::MakePaginationRange<ListHmacKeysReader>(
2592  request,
2593  [client](internal::ListHmacKeysRequest const& r) {
2594  return client->ListHmacKeys(r);
2595  },
2596  [](internal::ListHmacKeysResponse r) { return std::move(r.items); });
2597  }
2598 
2599  /**
2600  * Create a new HMAC key.
2601  *
2602  * @param service_account the service account email where you want to create
2603  * the new HMAC key.
2604  * @param options a list of optional query parameters and/or request headers.
2605  * In addition to the options common to all requests, this operation
2606  * accepts `OverrideDefaultProject`.
2607  *
2608  * @return This operation returns the new HMAC key metadata *and* the HMAC key
2609  * secret (encoded as a base64 string). This is the only request that
2610  * returns the secret.
2611  *
2612  * @par Idempotency
2613  * This operation is not idempotent. Retrying the operation will create a new
2614  * key each time.
2615  *
2616  * @par Example
2617  * @snippet storage_service_account_samples.cc create hmac key
2618  *
2619  * @par Example
2620  * @snippet storage_service_account_samples.cc create hmac key project
2621  *
2622  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2623  * general information on using HMAC keys for Google Cloud Platform
2624  * service accounts authentication.
2625  *
2626  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2627  * for a detailed description on how to use the feature.
2628  */
2629  template <typename... Options>
2630  StatusOr<std::pair<HmacKeyMetadata, std::string>> CreateHmacKey(
2631  std::string service_account, Options&&... options) {
2632  google::cloud::internal::OptionsSpan const span(
2633  SpanOptions(std::forward<Options>(options)...));
2634  auto const& project_id = raw_client_->client_options().project_id();
2635  internal::CreateHmacKeyRequest request(project_id,
2636  std::move(service_account));
2637  request.set_multiple_options(std::forward<Options>(options)...);
2638  auto result = raw_client_->CreateHmacKey(request);
2639  if (!result) {
2640  return result.status();
2641  }
2642  return std::make_pair(std::move(result->metadata),
2643  std::move(result->secret));
2644  }
2645 
2646  /**
2647  * Delete a HMAC key in a given project.
2648  *
2649  * @param access_id the HMAC key `access_id()` that you want to delete. Each
2650  * HMAC key is assigned an `access_id()` attribute at creation time.
2651  * @param options a list of optional query parameters and/or request headers.
2652  * In addition to the options common to all requests, this operation
2653  * accepts `OverrideDefaultProject`.
2654  *
2655  * @return This operation returns the new HMAC key metadata.
2656  *
2657  * @par Idempotency
2658  * This operation is always idempotent. An access id identifies a single HMAC
2659  * key, calling the operation multiple times can succeed only once.
2660  *
2661  * @par Example
2662  * @snippet storage_service_account_samples.cc delete hmac key
2663  *
2664  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2665  * general information on using HMAC keys for Google Cloud Platform
2666  * service accounts authentication.
2667  *
2668  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2669  * for a detailed description on how to use the feature.
2670  */
2671  template <typename... Options>
2672  Status DeleteHmacKey(std::string access_id, Options&&... options) {
2673  google::cloud::internal::OptionsSpan const span(
2674  SpanOptions(std::forward<Options>(options)...));
2675  auto const& project_id = raw_client_->client_options().project_id();
2676  internal::DeleteHmacKeyRequest request(project_id, std::move(access_id));
2677  request.set_multiple_options(std::forward<Options>(options)...);
2678  return raw_client_->DeleteHmacKey(request).status();
2679  }
2680 
2681  /**
2682  * Get an existing HMAC key in a given project.
2683  *
2684  * @param access_id the HMAC key `access_id()` that you want to delete. Each
2685  * HMAC key is assigned an `access_id()` attribute at creation time.
2686  * @param options a list of optional query parameters and/or request headers.
2687  * In addition to the options common to all requests, this operation
2688  * accepts `OverrideDefaultProject`.
2689  *
2690  * @return This operation returns the new HMAC key metadata.
2691  *
2692  * @par Idempotency
2693  * This is a read-only operation and therefore it is always idempotent.
2694  *
2695  * @par Example
2696  * @snippet storage_service_account_samples.cc get hmac key
2697  *
2698  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2699  * general information on using HMAC keys for Google Cloud Platform
2700  * service accounts authentication.
2701  *
2702  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2703  * for a detailed description on how to use the feature.
2704  */
2705  template <typename... Options>
2706  StatusOr<HmacKeyMetadata> GetHmacKey(std::string access_id,
2707  Options&&... options) {
2708  google::cloud::internal::OptionsSpan const span(
2709  SpanOptions(std::forward<Options>(options)...));
2710  auto const& project_id = raw_client_->client_options().project_id();
2711  internal::GetHmacKeyRequest request(project_id, std::move(access_id));
2712  request.set_multiple_options(std::forward<Options>(options)...);
2713  return raw_client_->GetHmacKey(request);
2714  }
2715 
2716  /**
2717  * Update an existing HMAC key in a given project.
2718  *
2719  * @param access_id the HMAC key `access_id()` that you want to delete. Each
2720  * HMAC key is assigned an `access_id()` attribute at creation time.
2721  * @param resource the desired changes to the HMAC key resource. Only the
2722  * `state` field may be changed. The `etag` field may be set but it is
2723  * only used as a pre-condition, the application cannot set the `etag`.
2724  * @param options a list of optional query parameters and/or request headers.
2725  * In addition to the options common to all requests, this operation
2726  * accepts `OverrideDefaultProject`.
2727  *
2728  * @return This operation returns the new HMAC key metadata.
2729  *
2730  * @par Idempotency
2731  * This operation is only idempotent if the `etag` attribute in @p resource
2732  * is set, or if the `IfMatchEtag` option is set.
2733  *
2734  * @par Example
2735  * @snippet storage_service_account_samples.cc update hmac key
2736  *
2737  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2738  * general information on using HMAC keys for Google Cloud Platform
2739  * service accounts authentication.
2740  *
2741  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2742  * for a detailed description on how to use the feature.
2743  */
2744  template <typename... Options>
2745  StatusOr<HmacKeyMetadata> UpdateHmacKey(std::string access_id,
2746  HmacKeyMetadata resource,
2747  Options&&... options) {
2748  google::cloud::internal::OptionsSpan const span(
2749  SpanOptions(std::forward<Options>(options)...));
2750  auto const& project_id = raw_client_->client_options().project_id();
2751  internal::UpdateHmacKeyRequest request(project_id, std::move(access_id),
2752  std::move(resource));
2753  request.set_multiple_options(std::forward<Options>(options)...);
2754  return raw_client_->UpdateHmacKey(request);
2755  }
2756  ///@}
2757 
2758  /// @name Signed URL support operations.
2759  ///@{
2760  /**
2761  * Create a V2 signed URL for the given parameters.
2762  *
2763  * @note By default URLs created with this function expire after 7 days.
2764  *
2765  * @note The application must ensure that any URL created with this function
2766  * is a valid request via the XML API. For example, the options for
2767  * bucket requests may include a sub-resource (e.g. `WithBilling()`) but
2768  * not all sub-resources are valid for objects. Likewise, only a single
2769  * sub-resource may be retrieved in each request.
2770  *
2771  * @param verb the operation allowed through this signed URL, `GET`, `POST`,
2772  * `PUT`, `HEAD`, etc. are valid values.
2773  * @param bucket_name the name of the bucket.
2774  * @param object_name the name of the object, note that the object may not
2775  * exist for signed URLs that upload new objects. Use an empty string for
2776  * requests that only affect a bucket.
2777  * @param options a list of optional parameters for the signed URL, this
2778  * include: `ExpirationTime`, `MD5HashValue`, `ContentType`,
2779  * `SigningAccount`, `SigningAccountDelegates`,
2780  * `AddExtensionHeaderOption`, `AddQueryParameterOption`, and
2781  * `AddSubResourceOption`. Note that only the last `AddSubResourceOption`
2782  * option has any effect.
2783  *
2784  * @par Helper Functions
2785  *
2786  * The following functions create a `AddSubResourceOption` with less
2787  * opportunities for typos in the sub-resource name: `WithAcl()`,
2788  * `WithBilling()`, `WithCompose()`, `WithCors()`, `WithEncryption()`,
2789  * `WithEncryptionConfig()`, `WithLifecycle()`, `WithLocation()`,
2790  * `WithLogging()`, `WithStorageClass()`, and `WithTagging()`.
2791  *
2792  * Likewise, the following helper functions can create properly formatted
2793  * `AddExtensionHeaderOption` objects: `WithGeneration()`,
2794  * `WithGenerationMarker()`, `WithMarker()`,
2795  * `WithResponseContentDisposition()`, `WithResponseContentType()`, and
2796  * `WithUserProject()`.
2797  *
2798  * @return the signed URL.
2799  *
2800  * @par Example
2801  * @snippet storage_signed_url_v2_samples.cc sign url v2
2802  *
2803  * @par Example
2804  * @snippet storage_signed_url_v2_samples.cc create put signed url v2
2805  *
2806  * @see https://cloud.google.com/storage/docs/access-control/signed-urls for
2807  * a general description of signed URLs and how they can be used.
2808  *
2809  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2810  * description of the XML API.
2811  */
2812  template <typename... Options>
2813  StatusOr<std::string> CreateV2SignedUrl(std::string verb,
2814  std::string bucket_name,
2815  std::string object_name,
2816  Options&&... options) {
2817  google::cloud::internal::OptionsSpan const span(
2818  SpanOptions(std::forward<Options>(options)...));
2819  internal::V2SignUrlRequest request(std::move(verb), std::move(bucket_name),
2820  std::move(object_name));
2821  request.set_multiple_options(std::forward<Options>(options)...);
2822  return SignUrlV2(request);
2823  }
2824 
2825  /**
2826  * Create a V4 signed URL for the given parameters.
2827  *
2828  * @note By default URLs created with this function expire after 7 days.
2829  *
2830  * @note The application must ensure that any URL created with this function
2831  * is a valid request via the XML API. For example, the options for
2832  * bucket requests may include a sub-resource (e.g. `WithBilling()`) but
2833  * not all sub-resources are valid for objects. Likewise, only a single
2834  * sub-resource may be retrieved in each request.
2835  *
2836  * @param verb the operation allowed through this signed URL, `GET`, `POST`,
2837  * `PUT`, `HEAD`, etc. are valid values.
2838  * @param bucket_name the name of the bucket.
2839  * @param object_name the name of the object, note that the object may not
2840  * exist for signed URLs that upload new objects. Use an empty string for
2841  * requests that only affect a bucket.
2842  * @param options a list of optional parameters for the signed URL, this
2843  * include: `SignedUrlTimestamp`, `SignedUrlDuration`, `MD5HashValue`,
2844  * `ContentType`, `SigningAccount`, `SigningAccountDelegates`,
2845  * `AddExtensionHeaderOption`, `AddQueryParameterOption`, and
2846  * `AddSubResourceOption`. Note that only the last `AddSubResourceOption`
2847  * option has any effect.
2848  *
2849  * @par Helper Functions
2850  *
2851  * The following functions create a `AddSubResourceOption` with less
2852  * opportunities for typos in the sub-resource name: `WithAcl()`,
2853  * `WithBilling()`, `WithCompose()`, `WithCors()`, `WithEncryption()`,
2854  * `WithEncryptionConfig()`, `WithLifecycle()`, `WithLocation()`,
2855  * `WithLogging()`, `WithStorageClass()`, and `WithTagging()`.
2856  *
2857  * Likewise, the following helper functions can create properly formatted
2858  * `AddExtensionHeaderOption` objects: `WithGeneration()`,
2859  * `WithGenerationMarker()`, `WithMarker()`,
2860  * `WithResponseContentDisposition()`, `WithResponseContentType()`, and
2861  * `WithUserProject()`.
2862  *
2863  * @return the signed URL.
2864  *
2865  * @par Example
2866  * @snippet storage_signed_url_v4_samples.cc sign url v4
2867  *
2868  * @par Example
2869  * @snippet storage_signed_url_v4_samples.cc create put signed url v4
2870  *
2871  * @see https://cloud.google.com/storage/docs/access-control/signed-urls for
2872  * a general description of signed URLs and how they can be used.
2873  *
2874  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2875  * description of the XML API.
2876  */
2877  template <typename... Options>
2878  StatusOr<std::string> CreateV4SignedUrl(std::string verb,
2879  std::string bucket_name,
2880  std::string object_name,
2881  Options&&... options) {
2882  google::cloud::internal::OptionsSpan const span(
2883  SpanOptions(std::forward<Options>(options)...));
2884  internal::V4SignUrlRequest request(std::move(verb), std::move(bucket_name),
2885  std::move(object_name));
2886  request.set_multiple_options(std::forward<Options>(options)...);
2887  return SignUrlV4(std::move(request));
2888  }
2889  ///@}
2890 
2891  /**
2892  * Create a signed policy document.
2893  *
2894  * @note The application must ensure that any document created with this
2895  * function contains valid conditions. This function does not do any error
2896  * checking, e.g. that a `ExactMatchObject()` condition contains two
2897  * elements. Using the provided helper functions can prevent errors.
2898  *
2899  * @note It is the application's responsibility to construct a POST request
2900  * based on the value returned by this function. For example, a web
2901  * application can create a HTML form containing these fields, the result of
2902  * which is a POST request to GCS.
2903  *
2904  * @param document the policy document.
2905  * @param options a list of optional parameters, this includes:
2906  * `SigningAccount`, and `SigningAccountDelegates`.
2907  *
2908  * @par Helper Functions
2909  * The following functions create a `PolicyDocumentCondition` with less
2910  * opportunities for typos: `StartsWith()`, `ExactMatchObject()`,
2911  * `ExactMatch()`, `ContentLengthRange()`.
2912  *
2913  * @par Example
2914  * @snippet storage_policy_doc_samples.cc create signed policy document
2915  *
2916  * @see
2917  * https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
2918  * for a general description of policy documents and how they can be used.
2919  *
2920  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2921  * description of the XML API.
2922  */
2923  template <typename... Options>
2925  PolicyDocument document, Options&&... options) {
2926  google::cloud::internal::OptionsSpan const span(
2927  SpanOptions(std::forward<Options>(options)...));
2928  internal::PolicyDocumentRequest request(std::move(document));
2929  request.set_multiple_options(std::forward<Options>(options)...);
2930  return SignPolicyDocument(request);
2931  }
2932 
2933  /**
2934  * Create a signed V4 policy document.
2935  *
2936  * @note The application must ensure that any document created with this
2937  * function contains valid conditions. This function does not do any error
2938  * checking, e.g. that a `ExactMatchObject()` condition contains two
2939  * elements. Using the provided helper functions can prevent errors.
2940  *
2941  * @note It is the application's responsibility to construct a POST request
2942  * based on the value returned by this function. For example, a web
2943  * application can create a HTML form containing these fields, the result of
2944  * which is a POST request to GCS.
2945  *
2946  * @param document the policy document.
2947  * @param options a list of optional parameters, this includes:
2948  * `AddExtensionFieldOption`, `BucketBoundHostname`, `PredefinedAcl`,
2949  * `Scheme`, `SigningAccountDelegates`, `SigningAccount`, `VirtualHostname`
2950  *
2951  * @par Helper Functions
2952  * The following functions create a `PolicyDocumentCondition` with less
2953  * opportunities for typos: `StartsWith()`, `ExactMatchObject()`,
2954  * `ExactMatch()`, `ContentLengthRange()`.
2955  *
2956  * @par Example
2957  * @snippet storage_policy_doc_samples.cc create signed policy document v4
2958  *
2959  * @see
2960  * https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
2961  * for a general description of policy documents and how they can be used.
2962  *
2963  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2964  * description of the XML API.
2965  */
2966  template <typename... Options>
2968  PolicyDocumentV4 document, Options&&... options) {
2969  google::cloud::internal::OptionsSpan const span(
2970  SpanOptions(std::forward<Options>(options)...));
2971  internal::PolicyDocumentV4Request request(std::move(document));
2972  request.set_multiple_options(std::forward<Options>(options)...);
2973  return SignPolicyDocumentV4(std::move(request));
2974  }
2975 
2976  /**
2977  * @name Pub/Sub operations.
2978  *
2979  * Cloud Pub/Sub Notifications sends information about changes to objects in
2980  * your buckets to Cloud Pub/Sub, where the information is added to a Cloud
2981  * Pub/Sub topic of your choice in the form of messages.
2982  *
2983  * @see https://cloud.google.com/storage/docs/pubsub-notifications for more
2984  * information about Cloud Pub/Sub in the context of GCS.
2985  */
2986  ///@{
2987  /**
2988  * Retrieves the list of Notifications for a Bucket.
2989  *
2990  * Cloud Pub/Sub Notifications sends information about changes to objects
2991  * in your buckets to Google Cloud Pub/Sub service.
2992  *
2993  * @param bucket_name the name of the bucket.
2994  * @param options a list of optional query parameters and/or request headers.
2995  * Valid types for this operation include `UserProject`.
2996  *
2997  * @par Idempotency
2998  * This is a read-only operation and is always idempotent.
2999  *
3000  * @par Example
3001  * @snippet storage_notification_samples.cc list notifications
3002  */
3003  template <typename... Options>
3004  StatusOr<std::vector<NotificationMetadata>> ListNotifications(
3005  std::string const& bucket_name, Options&&... options) {
3006  google::cloud::internal::OptionsSpan const span(
3007  SpanOptions(std::forward<Options>(options)...));
3008  internal::ListNotificationsRequest request(bucket_name);
3009  request.set_multiple_options(std::forward<Options>(options)...);
3010  auto result = raw_client_->ListNotifications(request);
3011  if (!result) {
3012  return std::move(result).status();
3013  }
3014  return std::move(result.value().items);
3015  }
3016 
3017  /**
3018  * Creates a new notification config for a Bucket.
3019  *
3020  * Cloud Pub/Sub Notifications send information about changes to objects
3021  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3022  * notifications per Bucket, with different topics and filtering options.
3023  *
3024  * @param bucket_name the name of the bucket.
3025  * @param topic_name the Google Cloud Pub/Sub topic that will receive the
3026  * notifications. This requires the full name of the topic, i.e.:
3027  * `projects/<PROJECT_ID>/topics/<TOPIC_ID>`.
3028  * @param metadata define any optional parameters for the notification, such
3029  * as the list of event types, or any custom attributes.
3030  * @param options a list of optional query parameters and/or request headers.
3031  * Valid types for this operation include `UserProject`.
3032  *
3033  * @par Idempotency
3034  * This operation is only idempotent if restricted by pre-conditions. There
3035  * are no pre-conditions for this operation that can make it idempotent.
3036  *
3037  * @par Example
3038  * @snippet storage_notification_samples.cc create notification
3039  *
3040  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3041  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3042  *
3043  * @see https://cloud.google.com/pubsub/ for general information on Google
3044  * Cloud Pub/Sub service.
3045  */
3046  template <typename... Options>
3048  std::string const& bucket_name, std::string const& topic_name,
3049  NotificationMetadata metadata, Options&&... options) {
3050  google::cloud::internal::OptionsSpan const span(
3051  SpanOptions(std::forward<Options>(options)...));
3052  return CreateNotification(bucket_name, topic_name,
3053  payload_format::JsonApiV1(), std::move(metadata),
3054  std::forward<Options>(options)...);
3055  }
3056 
3057  /**
3058  * Creates a new notification config for a Bucket.
3059  *
3060  * Cloud Pub/Sub Notifications send information about changes to objects
3061  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3062  * notifications per Bucket, with different topics and filtering options.
3063  *
3064  * @param bucket_name the name of the bucket.
3065  * @param topic_name the Google Cloud Pub/Sub topic that will receive the
3066  * notifications. This requires the full name of the topic, i.e.:
3067  * `projects/<PROJECT_ID>/topics/<TOPIC_ID>`.
3068  * @param payload_format how will the data be formatted in the notifications,
3069  * consider using the helpers in the `payload_format` namespace, or
3070  * specify one of the valid formats defined in:
3071  * https://cloud.google.com/storage/docs/json_api/v1/notifications
3072  * @param metadata define any optional parameters for the notification, such
3073  * as the list of event types, or any custom attributes.
3074  * @param options a list of optional query parameters and/or request headers.
3075  * Valid types for this operation include `UserProject`.
3076  *
3077  * @par Idempotency
3078  * This operation is only idempotent if restricted by pre-conditions. There
3079  * are no pre-conditions for this operation that can make it idempotent.
3080  *
3081  * @par Example
3082  * @snippet storage_notification_samples.cc create notification
3083  *
3084  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3085  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3086  *
3087  * @see https://cloud.google.com/pubsub/ for general information on Google
3088  * Cloud Pub/Sub service.
3089  */
3090  template <typename... Options>
3092  std::string const& bucket_name, std::string const& topic_name,
3093  std::string const& payload_format, NotificationMetadata metadata,
3094  Options&&... options) {
3095  google::cloud::internal::OptionsSpan const span(
3096  SpanOptions(std::forward<Options>(options)...));
3097  metadata.set_topic(topic_name).set_payload_format(payload_format);
3098  internal::CreateNotificationRequest request(bucket_name, metadata);
3099  request.set_multiple_options(std::forward<Options>(options)...);
3100  return raw_client_->CreateNotification(request);
3101  }
3102 
3103  /**
3104  * Gets the details about a notification config in a given Bucket.
3105  *
3106  * Cloud Pub/Sub Notifications sends information about changes to objects
3107  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3108  * notifications per Bucket, with different topics and filtering options. This
3109  * function fetches the detailed information for a given notification config.
3110  *
3111  * @param bucket_name the name of the bucket.
3112  * @param notification_id the id of the notification config.
3113  * @param options a list of optional query parameters and/or request headers.
3114  * Valid types for this operation include `UserProject`.
3115  *
3116  * @par Idempotency
3117  * This is a read-only operation and is always idempotent.
3118  *
3119  * @par Example
3120  * @snippet storage_notification_samples.cc get notification
3121  *
3122  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3123  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3124  *
3125  * @see https://cloud.google.com/pubsub/ for general information on Google
3126  * Cloud Pub/Sub service.
3127  */
3128  template <typename... Options>
3130  std::string const& bucket_name, std::string const& notification_id,
3131  Options&&... options) {
3132  google::cloud::internal::OptionsSpan const span(
3133  SpanOptions(std::forward<Options>(options)...));
3134  internal::GetNotificationRequest request(bucket_name, notification_id);
3135  request.set_multiple_options(std::forward<Options>(options)...);
3136  return raw_client_->GetNotification(request);
3137  }
3138 
3139  /**
3140  * Delete an existing notification config in a given Bucket.
3141  *
3142  * Cloud Pub/Sub Notifications sends information about changes to objects
3143  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3144  * notifications per Bucket, with different topics and filtering options. This
3145  * function deletes one of the notification configs.
3146  *
3147  * @param bucket_name the name of the bucket.
3148  * @param notification_id the id of the notification config.
3149  * @param options a list of optional query parameters and/or request headers.
3150  * Valid types for this operation include `UserProject`.
3151  *
3152  * @par Idempotency
3153  * This operation is always idempotent because it only acts on a specific
3154  * `notification_id`, the state after calling this function multiple times is
3155  * to delete that notification. New notifications get different ids.
3156  *
3157  * @par Example
3158  * @snippet storage_notification_samples.cc delete notification
3159  *
3160  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3161  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3162  *
3163  * @see https://cloud.google.com/pubsub/ for general information on Google
3164  * Cloud Pub/Sub service.
3165  */
3166  template <typename... Options>
3167  Status DeleteNotification(std::string const& bucket_name,
3168  std::string const& notification_id,
3169  Options&&... options) {
3170  google::cloud::internal::OptionsSpan const span(
3171  SpanOptions(std::forward<Options>(options)...));
3172  internal::DeleteNotificationRequest request(bucket_name, notification_id);
3173  request.set_multiple_options(std::forward<Options>(options)...);
3174  return std::move(raw_client_->DeleteNotification(request)).status();
3175  }
3176  ///@}
3177 
3178  /**
3179  * Creates the default client type given the options.
3180  *
3181  * @param options the client options, these are used to control credentials,
3182  * buffer sizes, etc.
3183  * @param policies the client policies, these control the behavior of the
3184  * client, for example, how to backoff when an operation needs to be
3185  * retried, or what operations cannot be retried because they are not
3186  * idempotent.
3187  *
3188  * @deprecated use the constructor from `google::cloud::Options` instead.
3189  */
3190  template <typename... Policies>
3191  explicit Client(ClientOptions options, Policies&&... policies)
3192  : Client(InternalOnly{}, internal::ApplyPolicies(
3193  internal::MakeOptions(std::move(options)),
3194  std::forward<Policies>(policies)...)) {}
3195 
3196  /**
3197  * Creates the default client type given the credentials and policies.
3198  *
3199  * @param credentials a set of credentials to initialize the `ClientOptions`.
3200  * @param policies the client policies, these control the behavior of the
3201  * client, for example, how to backoff when an operation needs to be
3202  * retried, or what operations cannot be retried because they are not
3203  * idempotent.
3204  *
3205  * @deprecated use the constructor from `google::cloud::Options` instead.
3206  */
3207  template <typename... Policies>
3208  explicit Client(std::shared_ptr<oauth2::Credentials> credentials,
3209  Policies&&... policies)
3210  : Client(InternalOnly{},
3211  internal::ApplyPolicies(
3212  internal::DefaultOptions(std::move(credentials), {}),
3213  std::forward<Policies>(policies)...)) {}
3214 
3215  /**
3216  * Create a Client using ClientOptions::CreateDefaultClientOptions().
3217  *
3218  * @deprecated use the constructor from `google::cloud::Options` instead.
3219  */
3220  static StatusOr<Client> CreateDefaultClient();
3221 
3222  /// Builds a client and maybe override the retry, idempotency, and/or backoff
3223  /// policies.
3224  /// @deprecated This was intended only for test code, applications should not
3225  /// use it.
3226  template <typename... Policies>
3227 #if !defined(_MSC_VER) || _MSC_VER >= 1920
3228  GOOGLE_CLOUD_CPP_DEPRECATED(
3229  "applications should not need this."
3230  " Please use the constructors from ClientOptions instead."
3231  " For mocking, please use testing::ClientFromMock() instead."
3232  " Please file a bug at https://github.com/googleapis/google-cloud-cpp"
3233  " if you have a use-case not covered by these.")
3234 #endif // _MSC_VER
3235  // NOLINTNEXTLINE(performance-unnecessary-value-param)
3236  explicit Client(std::shared_ptr<internal::RawClient> client,
3237  Policies&&... policies)
3238  : Client(InternalOnlyNoDecorations{},
3239  CreateDefaultInternalClient(
3240  internal::ApplyPolicies(
3241  internal::DefaultOptions(
3242  client->client_options().credentials(), {}),
3243  std::forward<Policies>(policies)...),
3244  client)) {
3245  }
3246 
3247  /// Define a tag to disable automatic decorations of the RawClient.
3248  struct NoDecorations {};
3249 
3250  /// Builds a client with a specific RawClient, without decorations.
3251  /// @deprecated This was intended only for test code, applications should not
3252  /// use it.
3253  GOOGLE_CLOUD_CPP_DEPRECATED(
3254  "applications should not need this."
3255  " Please file a bug at https://github.com/googleapis/google-cloud-cpp"
3256  " if you do.")
3257  explicit Client(std::shared_ptr<internal::RawClient> client, NoDecorations)
3258  : Client(InternalOnlyNoDecorations{}, std::move(client)) {}
3259 
3260  /// Access the underlying `RawClient`.
3261  /// @deprecated Only intended for implementors, do not use.
3262  GOOGLE_CLOUD_CPP_DEPRECATED(
3263  "applications should not need this."
3264  " Please file a bug at https://github.com/googleapis/google-cloud-cpp"
3265  " if you do.")
3266  std::shared_ptr<internal::RawClient> raw_client() const {
3267  return raw_client_;
3268  }
3269 
3270  private:
3271  friend class internal::NonResumableParallelUploadState;
3272  friend class internal::ResumableParallelUploadState;
3273  friend internal::ClientImplDetails;
3274 
3275  struct InternalOnly {};
3276  struct InternalOnlyNoDecorations {};
3277 
3278  Client(InternalOnly, Options const& opts)
3279  : raw_client_(CreateDefaultInternalClient(opts)) {}
3280  Client(InternalOnlyNoDecorations, std::shared_ptr<internal::RawClient> c)
3281  : raw_client_(std::move(c)) {}
3282 
3283  static std::shared_ptr<internal::RawClient> CreateDefaultInternalClient(
3284  Options const& opts, std::shared_ptr<internal::RawClient> client);
3285  static std::shared_ptr<internal::RawClient> CreateDefaultInternalClient(
3286  Options const& opts);
3287 
3288  ObjectReadStream ReadObjectImpl(
3289  internal::ReadObjectRangeRequest const& request);
3290 
3291  ObjectWriteStream WriteObjectImpl(
3292  internal::ResumableUploadRequest const& request);
3293 
3294  template <typename... RequestOptions>
3295  google::cloud::Options SpanOptions(RequestOptions&&... o) const {
3296  return internal::GroupOptions(raw_client_->options(),
3297  std::forward<RequestOptions>(o)...);
3298  }
3299 
3300  // The version of UploadFile() where UseResumableUploadSession is one of the
3301  // options. Note how this does not use InsertObjectMedia at all.
3302  template <typename... Options>
3303  StatusOr<ObjectMetadata> UploadFileImpl(std::string const& file_name,
3304  std::string const& bucket_name,
3305  std::string const& object_name,
3306  std::true_type,
3307  Options&&... options) {
3308  google::cloud::internal::OptionsSpan const span(
3309  SpanOptions(std::forward<Options>(options)...));
3310  internal::ResumableUploadRequest request(bucket_name, object_name);
3311  request.set_multiple_options(std::forward<Options>(options)...);
3312  return UploadFileResumable(file_name, std::move(request));
3313  }
3314 
3315  // The version of UploadFile() where UseResumableUploadSession is *not* one of
3316  // the options. In this case we can use InsertObjectMediaRequest because it
3317  // is safe.
3318  template <typename... Options>
3319  StatusOr<ObjectMetadata> UploadFileImpl(std::string const& file_name,
3320  std::string const& bucket_name,
3321  std::string const& object_name,
3322  std::false_type,
3323  Options&&... options) {
3324  google::cloud::internal::OptionsSpan const span(
3325  SpanOptions(std::forward<Options>(options)...));
3326  std::size_t file_size = 0;
3327  if (UseSimpleUpload(file_name, file_size)) {
3328  internal::InsertObjectMediaRequest request(bucket_name, object_name,
3329  std::string{});
3330  request.set_multiple_options(std::forward<Options>(options)...);
3331  return UploadFileSimple(file_name, file_size, request);
3332  }
3333  internal::ResumableUploadRequest request(bucket_name, object_name);
3334  request.set_multiple_options(std::forward<Options>(options)...);
3335  return UploadFileResumable(file_name, std::move(request));
3336  }
3337 
3338  bool UseSimpleUpload(std::string const& file_name, std::size_t& size) const;
3339 
3340  StatusOr<ObjectMetadata> UploadFileSimple(
3341  std::string const& file_name, std::size_t file_size,
3342  internal::InsertObjectMediaRequest request);
3343 
3344  StatusOr<ObjectMetadata> UploadFileResumable(
3345  std::string const& file_name, internal::ResumableUploadRequest request);
3346 
3347  StatusOr<ObjectMetadata> UploadStreamResumable(
3348  std::istream& source,
3349  internal::ResumableUploadRequest const& request) const;
3350 
3351  Status DownloadFileImpl(internal::ReadObjectRangeRequest const& request,
3352  std::string const& file_name);
3353 
3354  /// Determine the email used to sign a blob.
3355  std::string SigningEmail(SigningAccount const& signing_account) const;
3356 
3357  /// Represents the result of signing a blob, including the key used in the
3358  /// signature.
3359  struct SignBlobResponseRaw {
3360  std::string key_id;
3361  std::vector<std::uint8_t> signed_blob;
3362  };
3363 
3364  /// Sign a blob.
3365  StatusOr<SignBlobResponseRaw> SignBlobImpl(
3366  SigningAccount const& signing_account, std::string const& string_to_sign);
3367 
3368  StatusOr<std::string> SignUrlV2(internal::V2SignUrlRequest const& request);
3369  StatusOr<std::string> SignUrlV4(internal::V4SignUrlRequest request);
3370 
3371  StatusOr<PolicyDocumentResult> SignPolicyDocument(
3372  internal::PolicyDocumentRequest const& request);
3373  StatusOr<PolicyDocumentV4Result> SignPolicyDocumentV4(
3374  internal::PolicyDocumentV4Request request);
3375 
3376  std::shared_ptr<internal::RawClient> raw_client_;
3377 };
3378 
3379 /**
3380  * Create a random prefix for object names.
3381  *
3382  * This is useful for operations which require a unique prefix for temporary
3383  * files.
3384  *
3385  * This is a helper function and it doesn't communicate with GCS, so there is a
3386  * very small chance that names generated this way aren't unique. The chance
3387  * should be small enough to fit any error budget.
3388  *
3389  * Given the same `prefix`, the randomly generated names will have the same
3390  * length.
3391  *
3392  * @param prefix the prefix of the prefix to be created.
3393  * @return the random prefix name
3394  */
3395 std::string CreateRandomPrefixName(std::string const& prefix = "");
3396 
3397 namespace internal {
3398 struct ClientImplDetails {
3399  static std::shared_ptr<RawClient> GetRawClient(Client& c) {
3400  return c.raw_client_;
3401  }
3402 
3403  static StatusOr<ObjectMetadata> UploadStreamResumable(
3404  Client& client, std::istream& source,
3405  internal::ResumableUploadRequest const& request) {
3406  return client.UploadStreamResumable(source, request);
3407  }
3408 
3409  template <typename... Policies>
3410  static Client CreateClient(std::shared_ptr<internal::RawClient> c,
3411  Policies&&... p) {
3412  auto opts =
3413  internal::ApplyPolicies(c->options(), std::forward<Policies>(p)...);
3414  return Client(Client::InternalOnlyNoDecorations{},
3415  Client::CreateDefaultInternalClient(opts, std::move(c)));
3416  }
3417 
3418  static Client CreateWithoutDecorations(
3419  std::shared_ptr<internal::RawClient> c) {
3420  return Client(Client::InternalOnlyNoDecorations{}, std::move(c));
3421  }
3422 };
3423 
3424 // Just a wrapper to allow for using in `google::cloud::internal::apply`.
3425 struct DeleteApplyHelper {
3426  template <typename... Options>
3427  Status operator()(Options... options) const {
3428  return client.DeleteObject(bucket_name, object_name, Generation(generation),
3429  std::move(options)...);
3430  }
3431 
3432  Client& client;
3433  std::string bucket_name;
3434  std::string object_name;
3435  std::int64_t generation;
3436 };
3437 
3438 // Just a wrapper to allow for using in `google::cloud::internal::apply`.
3439 struct InsertObjectApplyHelper {
3440  template <typename... Options>
3441  StatusOr<ObjectMetadata> operator()(Options... options) const {
3442  return client.InsertObject(bucket_name, object_name, std::move(contents),
3443  std::move(options)...);
3444  }
3445 
3446  Client& client;
3447  std::string const& bucket_name;
3448  std::string const& object_name;
3449  std::string contents;
3450 };
3451 
3452 /**
3453  * Create a "marker" object to ensure that two tasks cannot share a prefix.
3454  *
3455  * @param client the client on which to perform the operation.
3456  * @param bucket_name the name of the bucket that will contain the object.
3457  * @param prefix the prefix of the objects to be deleted.
3458  * @param options a list of optional query parameters and/or request headers.
3459  * Valid types for this operation include `EncryptionKey` `KmsKeyName`,
3460  * `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
3461  * Contrary to the public API, invalid options will be silently ignored
3462  * for ease of use.
3463  * @return the metadata of the marker
3464  */
3465 template <typename... Options>
3466 StatusOr<ObjectMetadata> LockPrefix(Client& client,
3467  std::string const& bucket_name,
3468  std::string const& prefix,
3469  Options&&... options) {
3470  return google::cloud::internal::apply(
3471  internal::InsertObjectApplyHelper{client, bucket_name, prefix, ""},
3472  std::tuple_cat(
3473  std::make_tuple(IfGenerationMatch(0)),
3474  internal::StaticTupleFilter<
3475  internal::Among<EncryptionKey, KmsKeyName, PredefinedAcl,
3476  Projection, UserProject>::TPred>(
3477  std::forward_as_tuple(std::forward<Options>(options)...))));
3478 }
3479 
3480 } // namespace internal
3481 
3482 /**
3483  * Delete objects whose names match a given prefix
3484  *
3485  * @param client the client on which to perform the operation.
3486  * @param bucket_name the name of the bucket that will contain the object.
3487  * @param prefix the prefix of the objects to be deleted.
3488  * @param options a list of optional query parameters and/or request headers.
3489  * Valid types for this operation include `QuotaUser`, `UserIp`,
3490  * `UserProject` and `Versions`.
3491  */
3492 template <typename... Options>
3493 Status DeleteByPrefix(Client& client, std::string const& bucket_name,
3494  std::string const& prefix, Options&&... options) {
3495  using internal::NotAmong;
3496  using internal::StaticTupleFilter;
3497 
3498  auto all_options = std::tie(options...);
3499 
3500  static_assert(
3501  std::tuple_size<
3502  decltype(StaticTupleFilter<
3503  NotAmong<QuotaUser, UserIp, UserProject, Versions>::TPred>(
3504  all_options))>::value == 0,
3505  "This functions accepts only options of type QuotaUser, UserIp, "
3506  "UserProject or Versions.");
3507  auto status = Status{};
3508  for (auto& object :
3509  client.ListObjects(bucket_name, Projection::NoAcl(), Prefix(prefix),
3510  std::forward<Options>(options)...)) {
3511  if (!object) return std::move(object).status();
3512  auto del = google::cloud::internal::apply(
3513  internal::DeleteApplyHelper{client, object->bucket(), object->name(),
3514  object->generation()},
3515  StaticTupleFilter<NotAmong<Versions>::TPred>(all_options));
3516  // We ignore kNotFound because we are trying to delete the object anyway.
3517  if (del.ok() || status.code() == StatusCode::kNotFound) continue;
3518  status = std::move(del);
3519  }
3520  return status;
3521 }
3522 
3523 namespace internal {
3524 
3525 // Just a wrapper to allow for use in `google::cloud::internal::apply`.
3526 struct ComposeApplyHelper {
3527  template <typename... Options>
3528  StatusOr<ObjectMetadata> operator()(Options... options) const {
3529  return client.ComposeObject(
3530  std::move(bucket_name), std::move(source_objects),
3531  std::move(destination_object_name), std::move(options)...);
3532  }
3533 
3534  Client& client;
3535  std::string bucket_name;
3536  std::vector<ComposeSourceObject> source_objects;
3537  std::string destination_object_name;
3538 };
3539 
3540 // A helper to defer deletion of temporary GCS objects.
3541 class ScopedDeleter {
3542  public:
3543  // The actual deletion depends on local's types in a very non-trivial way,
3544  // so we abstract this away by providing the function to delete one object.
3545  explicit ScopedDeleter(std::function<Status(std::string, std::int64_t)> df);
3546  ScopedDeleter(ScopedDeleter const&) = delete;
3547  ScopedDeleter& operator=(ScopedDeleter const&) = delete;
3548  ~ScopedDeleter();
3549 
3550  /// Defer object's deletion to this objects destruction (or ExecuteDelete())
3551  void Add(ObjectMetadata const& object);
3552 
3553  /// Defer object's deletion to this objects destruction (or ExecuteDelete())
3554  void Add(std::string object_name, std::int64_t generation);
3555 
3556  /// Execute all the deferred deletions now.
3557  Status ExecuteDelete();
3558 
3559  void Enable(bool enable) { enabled_ = enable; }
3560 
3561  private:
3562  bool enabled_ = true;
3563  std::function<Status(std::string, std::int64_t)> delete_fun_;
3564  std::vector<std::pair<std::string, std::int64_t>> object_list_;
3565 };
3566 
3567 } // namespace internal
3568 
3569 /**
3570  * Compose existing objects into a new object in the same bucket.
3571  *
3572  * Contrary to `Client::ComposeObject`, this function doesn't have a limit on
3573  * the number of source objects.
3574  *
3575  * The implementation may need to perform multiple Client::ComposeObject calls
3576  * to create intermediate, temporary objects which are then further composed.
3577  * Due to the lack of atomicity of this series of operations, stray temporary
3578  * objects might be left over if there are transient failures. In order to allow
3579  * the user to easily control for such situations, the user is expected to
3580  * provide a unique @p prefix parameter, which will become the prefix of all the
3581  * temporary objects created by this function. Once this function finishes, the
3582  * user may safely remove all objects with the provided prefix (e.g. via
3583  * DeleteByPrefix()). We recommend using CreateRandomPrefixName() for selecting
3584  * a random prefix within a bucket.
3585  *
3586  * @param client the client on which to perform the operations needed by this
3587  * function
3588  * @param bucket_name the name of the bucket used for source object and
3589  * destination object.
3590  * @param source_objects objects used to compose `destination_object_name`.
3591  * @param destination_object_name the composed object name.
3592  * @param prefix prefix for temporary objects created by this function; there
3593  * should not be any objects with this prefix; in order to avoid race
3594  * conditions, this function will create an object with this name
3595  * @param ignore_cleanup_failures if the composition succeeds but cleanup of
3596  * temporary objects fails, depending on this parameter either a success
3597  * will be returned (`true`) or the relevant cleanup error (`false`)
3598  * @param options a list of optional query parameters and/or request headers.
3599  * Valid types for this operation include `DestinationPredefinedAcl`,
3600  * `EncryptionKey`, `IfGenerationMatch`, `IfMetagenerationMatch`
3601  * `KmsKeyName`, `QuotaUser`, `UserIp`, `UserProject` and
3602  * `WithObjectMetadata`.
3603  *
3604  * @par Idempotency
3605  * This operation is not idempotent. While each request performed by this
3606  * function is retried based on the client policies, the operation itself stops
3607  * on the first request that fails.
3608  *
3609  * @par Example
3610  * @snippet storage_object_samples.cc compose object from many
3611  */
3612 template <typename... Options>
3614  Client& client, std::string const& bucket_name,
3615  std::vector<ComposeSourceObject> source_objects, std::string const& prefix,
3616  std::string destination_object_name, bool ignore_cleanup_failures,
3617  Options&&... options) {
3618  using internal::Among;
3619  using internal::NotAmong;
3620  using internal::StaticTupleFilter;
3621  std::size_t const max_num_objects = 32;
3622 
3623  if (source_objects.empty()) {
3625  "ComposeMany requires at least one source object.");
3626  }
3627 
3628  auto all_options = std::make_tuple(options...);
3629 
3630  // TODO(#3247): this list of type should somehow be generated
3631  static_assert(
3632  std::tuple_size<
3633  decltype(StaticTupleFilter<
3636  KmsKeyName, QuotaUser, UserIp, UserProject,
3637  WithObjectMetadata>::TPred>(all_options))>::value ==
3638  0,
3639  "This functions accepts only options of type DestinationPredefinedAcl, "
3640  "EncryptionKey, IfGenerationMatch, IfMetagenerationMatch, KmsKeyName, "
3641  "QuotaUser, UserIp, UserProject or WithObjectMetadata.");
3642 
3643  internal::ScopedDeleter deleter(
3644  [&](std::string const& object_name, std::int64_t generation) {
3645  return google::cloud::internal::apply(
3646  internal::DeleteApplyHelper{client, bucket_name, object_name,
3647  generation},
3648  StaticTupleFilter<Among<QuotaUser, UserProject, UserIp>::TPred>(
3649  all_options));
3650  });
3651 
3652  auto lock = internal::LockPrefix(client, bucket_name, prefix, "",
3653  std::make_tuple(options...));
3654  if (!lock) {
3655  return Status(
3656  lock.status().code(),
3657  "Failed to lock prefix for ComposeMany: " + lock.status().message());
3658  }
3659  deleter.Add(*lock);
3660 
3661  std::size_t num_tmp_objects = 0;
3662  auto tmpobject_name_gen = [&num_tmp_objects, &prefix] {
3663  return prefix + ".compose-tmp-" + std::to_string(num_tmp_objects++);
3664  };
3665 
3666  auto to_source_objects = [](std::vector<ObjectMetadata> objects) {
3667  std::vector<ComposeSourceObject> sources(objects.size());
3668  std::transform(objects.begin(), objects.end(), sources.begin(),
3669  [](ObjectMetadata const& m) {
3670  return ComposeSourceObject{m.name(), m.generation(), {}};
3671  });
3672  return sources;
3673  };
3674 
3675  auto composer = [&](std::vector<ComposeSourceObject> compose_range,
3676  bool is_final) -> StatusOr<ObjectMetadata> {
3677  if (is_final) {
3678  return google::cloud::internal::apply(
3679  internal::ComposeApplyHelper{client, bucket_name,
3680  std::move(compose_range),
3681  std::move(destination_object_name)},
3682  all_options);
3683  }
3684  return google::cloud::internal::apply(
3685  internal::ComposeApplyHelper{client, bucket_name,
3686  std::move(compose_range),
3687  tmpobject_name_gen()},
3688  StaticTupleFilter<
3689  NotAmong<IfGenerationMatch, IfMetagenerationMatch>::TPred>(
3690  all_options));
3691  };
3692 
3693  auto reduce = [&](std::vector<ComposeSourceObject> source_objects)
3694  -> StatusOr<std::vector<ObjectMetadata>> {
3695  std::vector<ObjectMetadata> objects;
3696  for (auto range_begin = source_objects.begin();
3697  range_begin != source_objects.end();) {
3698  std::size_t range_size = std::min<std::size_t>(
3699  std::distance(range_begin, source_objects.end()), max_num_objects);
3700  auto range_end = std::next(range_begin, range_size);
3701  std::vector<ComposeSourceObject> compose_range(range_size);
3702  std::move(range_begin, range_end, compose_range.begin());
3703 
3704  bool const is_final_composition =
3705  source_objects.size() <= max_num_objects;
3706  auto object = composer(std::move(compose_range), is_final_composition);
3707  if (!object) {
3708  return std::move(object).status();
3709  }
3710  objects.push_back(*std::move(object));
3711  if (!is_final_composition) {
3712  deleter.Add(objects.back());
3713  }
3714  range_begin = range_end;
3715  }
3716  return objects;
3717  };
3718 
3719  StatusOr<ObjectMetadata> result;
3720  do {
3721  StatusOr<std::vector<ObjectMetadata>> objects = reduce(source_objects);
3722  if (!objects) {
3723  return objects.status();
3724  }
3725  if (objects->size() == 1) {
3726  if (!ignore_cleanup_failures) {
3727  auto delete_status = deleter.ExecuteDelete();
3728  if (!delete_status.ok()) {
3729  return delete_status;
3730  }
3731  }
3732  result = std::move((*objects)[0]);
3733  break;
3734  }
3735  source_objects = to_source_objects(*std::move(objects));
3736  } while (source_objects.size() > 1);
3737  return result;
3738 }
3739 
3741 } // namespace storage
3742 } // namespace cloud
3743 } // namespace google
3744 
3745 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H