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