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