Google Cloud Storage C++ Client  1.33.0
A C++ Client Library for Google Cloud Storage
bucket_metadata.cc
Go to the documentation of this file.
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "google/cloud/storage/bucket_metadata.h"
16 #include "google/cloud/storage/internal/bucket_acl_requests.h"
17 #include "google/cloud/storage/internal/bucket_requests.h"
18 #include "google/cloud/storage/internal/metadata_parser.h"
19 #include "google/cloud/storage/internal/object_acl_requests.h"
20 #include "google/cloud/internal/absl_str_join_quiet.h"
21 #include "google/cloud/internal/format_time_point.h"
22 #include "google/cloud/internal/ios_flags_saver.h"
23 #include "google/cloud/status.h"
24 #include "absl/strings/str_format.h"
25 #include <nlohmann/json.hpp>
26 
27 namespace google {
28 namespace cloud {
29 namespace storage {
31 namespace internal {
32 absl::optional<std::string> const& NormalizePap(
33  absl::optional<std::string> const& pap) {
34  static auto const* normalized =
35  new absl::optional<std::string>(PublicAccessPreventionInherited());
36  if (!pap.has_value() || *pap != "unspecified") return pap;
37  return *normalized;
38 }
39 } // namespace internal
40 
41 std::ostream& operator<<(std::ostream& os, CorsEntry const& rhs) {
42  os << "CorsEntry={";
43  char const* sep = "";
44  if (rhs.max_age_seconds.has_value()) {
45  os << sep << "max_age_seconds=" << *rhs.max_age_seconds;
46  sep = ", ";
47  }
48  return os << sep << "method=[" << absl::StrJoin(rhs.method, ", ")
49  << "], origin=[" << absl::StrJoin(rhs.origin, ", ")
50  << "], response_header=["
51  << absl::StrJoin(rhs.response_header, ", ") << "]}";
52 }
53 
54 std::ostream& operator<<(std::ostream& os,
55  UniformBucketLevelAccess const& rhs) {
56  google::cloud::internal::IosFlagsSaver save_format(os);
57  return os << "UniformBucketLevelAccess={enabled=" << std::boolalpha
58  << rhs.enabled << ", locked_time="
59  << google::cloud::internal::FormatRfc3339(rhs.locked_time) << "}";
60 }
61 
62 std::ostream& operator<<(std::ostream& os, BucketIamConfiguration const& rhs) {
63  os << "BucketIamConfiguration={";
64  char const* sep = "";
65  if (rhs.public_access_prevention.has_value()) {
66  os << sep << "public_access_prevention=" << *rhs.public_access_prevention;
67  sep = ", ";
68  }
69  if (rhs.uniform_bucket_level_access.has_value()) {
70  os << sep
71  << "uniform_bucket_level_access=" << *rhs.uniform_bucket_level_access;
72  return os << "}";
73  }
74  return os << "}";
75 }
76 
77 std::ostream& operator<<(std::ostream& os, BucketLogging const& rhs) {
78  return os << "BucketLogging={log_bucket=" << rhs.log_bucket
79  << ", log_object_prefix=" << rhs.log_object_prefix << "}";
80 }
81 
82 std::ostream& operator<<(std::ostream& os, BucketRetentionPolicy const& rhs) {
83  return os << "BucketRetentionPolicy={retention_period="
84  << rhs.retention_period.count() << "s, effective_time="
85  << google::cloud::internal::FormatRfc3339(rhs.effective_time)
86  << ", locked=" << rhs.is_locked << "}";
87 }
88 
89 bool operator==(BucketMetadata const& lhs, BucketMetadata const& rhs) {
90  return static_cast<internal::CommonMetadata<BucketMetadata> const&>(lhs) ==
91  rhs &&
92  lhs.acl_ == rhs.acl_ && lhs.billing_ == rhs.billing_ &&
93  lhs.cors_ == rhs.cors_ &&
94  lhs.default_event_based_hold_ == rhs.default_event_based_hold_ &&
95  lhs.default_acl_ == rhs.default_acl_ &&
96  lhs.encryption_ == rhs.encryption_ &&
97  lhs.iam_configuration_ == rhs.iam_configuration_ &&
98  lhs.project_number_ == rhs.project_number_ &&
99  lhs.lifecycle_ == rhs.lifecycle_ && lhs.location_ == rhs.location_ &&
100  lhs.location_type_ == rhs.location_type_ &&
101  lhs.logging_ == rhs.logging_ && lhs.labels_ == rhs.labels_ &&
102  lhs.retention_policy_ == rhs.retention_policy_ &&
103  lhs.rpo_ == rhs.rpo_ && lhs.versioning_ == rhs.versioning_ &&
104  lhs.website_ == rhs.website_;
105 }
106 
107 std::ostream& operator<<(std::ostream& os, BucketMetadata const& rhs) {
108  google::cloud::internal::IosFlagsSaver save_format(os);
109  os << "BucketMetadata={name=" << rhs.name();
110 
111  os << ", acl=[";
112  os << absl::StrJoin(rhs.acl(), ", ", absl::StreamFormatter());
113  os << "]";
114 
115  if (rhs.has_billing()) {
116  auto previous_flags = os.flags();
117  os << ", billing.requesterPays=" << std::boolalpha
119  os.flags(previous_flags);
120  }
121 
122  os << ", cors=[";
123  os << absl::StrJoin(rhs.cors(), ", ", absl::StreamFormatter());
124  os << "]";
125 
126  os << ", default_event_based_hold=" << std::boolalpha
128 
129  os << ", default_acl=[";
130  os << absl::StrJoin(rhs.default_acl(), ", ", absl::StreamFormatter());
131  os << "]";
132 
133  if (rhs.has_encryption()) {
134  os << ", encryption.default_kms_key_name="
136  }
137 
138  os << ", etag=" << rhs.etag();
139 
140  if (rhs.has_iam_configuration()) {
141  os << ", iam_configuration=" << rhs.iam_configuration();
142  }
143 
144  os << ", id=" << rhs.id() << ", kind=" << rhs.kind();
145 
146  for (auto const& kv : rhs.labels_) {
147  os << ", labels." << kv.first << "=" << kv.second;
148  }
149 
150  if (rhs.has_lifecycle()) {
151  os << ", lifecycle.rule=[";
152  os << absl::StrJoin(rhs.lifecycle().rule, ", ", absl::StreamFormatter());
153  os << "]";
154  }
155 
156  os << ", location=" << rhs.location();
157 
158  os << ", location_type=" << rhs.location_type();
159 
160  if (rhs.has_logging()) {
161  os << ", logging=" << rhs.logging();
162  }
163 
164  os << ", metageneration=" << rhs.metageneration() << ", name=" << rhs.name();
165 
166  if (rhs.has_owner()) {
167  os << ", owner.entity=" << rhs.owner().entity
168  << ", owner.entity_id=" << rhs.owner().entity_id;
169  }
170 
171  os << ", project_number=" << rhs.project_number()
172  << ", self_link=" << rhs.self_link()
173  << ", storage_class=" << rhs.storage_class() << ", time_created="
174  << google::cloud::internal::FormatRfc3339(rhs.time_created())
175  << ", updated=" << google::cloud::internal::FormatRfc3339(rhs.updated());
176 
177  if (rhs.has_retention_policy()) {
178  os << ", retention_policy.retention_period="
180  << ", retention_policy.effective_time="
181  << google::cloud::internal::FormatRfc3339(
183  << ", retention_policy.is_locked=" << std::boolalpha
185  }
186 
187  os << ", rpo=" << rhs.rpo();
188 
189  if (rhs.versioning().has_value()) {
190  auto previous_flags = os.flags();
191  os << ", versioning.enabled=" << std::boolalpha
192  << rhs.versioning()->enabled;
193  os.flags(previous_flags);
194  }
195 
196  if (rhs.has_website()) {
197  os << ", website.main_page_suffix=" << rhs.website().main_page_suffix
198  << ", website.not_found_page=" << rhs.website().not_found_page;
199  }
200 
201  return os << "}";
202 }
203 
205  internal::PatchBuilder tmp = impl_;
206  if (labels_subpatch_dirty_) {
207  if (labels_subpatch_.empty()) {
208  tmp.RemoveField("labels");
209  } else {
210  tmp.AddSubPatch("labels", labels_subpatch_);
211  }
212  }
213  return tmp.ToString();
214 }
215 
217  std::vector<BucketAccessControl> const& v) {
218  if (v.empty()) {
219  return ResetAcl();
220  }
221  auto array = nlohmann::json::array();
222  for (auto const& a : v) {
223  array.emplace_back(nlohmann::json{
224  {"entity", a.entity()},
225  {"role", a.role()},
226  });
227  }
228  impl_.SetArrayField("acl", array.dump());
229  return *this;
230 }
231 
233  impl_.RemoveField("acl");
234  return *this;
235 }
236 
238  BucketBilling const& v) {
239  impl_.AddSubPatch("billing", internal::PatchBuilder().SetBoolField(
240  "requesterPays", v.requester_pays));
241  return *this;
242 }
243 
245  impl_.RemoveField("billing");
246  return *this;
247 }
248 
250  std::vector<CorsEntry> const& v) {
251  if (v.empty()) {
252  return ResetCors();
253  }
254  auto array = nlohmann::json::array();
255  for (auto const& a : v) {
256  nlohmann::json entry;
257  if (a.max_age_seconds.has_value()) {
258  entry["maxAgeSeconds"] = *a.max_age_seconds;
259  }
260  if (!a.method.empty()) {
261  entry["method"] = a.method;
262  }
263  if (!a.origin.empty()) {
264  entry["origin"] = a.origin;
265  }
266  if (!a.response_header.empty()) {
267  entry["responseHeader"] = a.response_header;
268  }
269  array.emplace_back(std::move(entry));
270  }
271  impl_.SetArrayField("cors", array.dump());
272  return *this;
273 }
274 
276  impl_.RemoveField("cors");
277  return *this;
278 }
279 
282  impl_.SetBoolField("defaultEventBasedHold", v);
283  return *this;
284 }
285 
288  impl_.RemoveField("defaultEventBasedHold");
289  return *this;
290 }
291 
293  std::vector<ObjectAccessControl> const& v) {
294  if (v.empty()) {
295  return ResetDefaultAcl();
296  }
297  auto array = nlohmann::json::array();
298  for (auto const& a : v) {
299  array.emplace_back(nlohmann::json{
300  {"entity", a.entity()},
301  {"role", a.role()},
302  });
303  }
304  impl_.SetArrayField("defaultObjectAcl", array.dump());
305  return *this;
306 }
307 
309  impl_.RemoveField("defaultObjectAcl");
310  return *this;
311 }
312 
314  BucketEncryption const& v) {
315  impl_.AddSubPatch("encryption",
316  internal::PatchBuilder().SetStringField(
317  "defaultKmsKeyName", v.default_kms_key_name));
318  return *this;
319 }
320 
322  impl_.RemoveField("encryption");
323  return *this;
324 }
325 
327  BucketIamConfiguration const& v) {
328  internal::PatchBuilder iam_configuration;
329 
330  if (v.public_access_prevention.has_value()) {
331  iam_configuration.SetStringField("publicAccessPrevention",
333  }
334  if (v.uniform_bucket_level_access.has_value()) {
335  internal::PatchBuilder uniform_bucket_level_access;
336  uniform_bucket_level_access.SetBoolField(
338  // The lockedTime field should not be set, this is not a mutable field, it
339  // is set by the server when the policy is enabled.
340  iam_configuration.AddSubPatch("uniformBucketLevelAccess",
341  uniform_bucket_level_access);
342  impl_.AddSubPatch("iamConfiguration", iam_configuration);
343  return *this;
344  }
345  impl_.AddSubPatch("iamConfiguration", iam_configuration);
346  return *this;
347 }
348 
351  impl_.RemoveField("iamConfiguration");
352  return *this;
353 }
354 
356  std::string const& label, std::string const& value) {
357  labels_subpatch_.SetStringField(label.c_str(), value);
358  labels_subpatch_dirty_ = true;
359  return *this;
360 }
361 
363  std::string const& label) {
364  labels_subpatch_.RemoveField(label.c_str());
365  labels_subpatch_dirty_ = true;
366  return *this;
367 }
368 
370  labels_subpatch_.clear();
371  labels_subpatch_dirty_ = true;
372  return *this;
373 }
374 
376  BucketLifecycle const& v) {
377  if (v.rule.empty()) {
378  return ResetLifecycle();
379  }
380  internal::PatchBuilder subpatch;
381  auto array = nlohmann::json::array();
382  for (auto const& a : v.rule) {
383  nlohmann::json condition;
384  auto const& c = a.condition();
385  if (c.age.has_value()) {
386  condition["age"] = *c.age;
387  }
388  if (c.created_before.has_value()) {
389  condition["createdBefore"] =
390  absl::StrFormat("%04d-%02d-%02d", c.created_before->year(),
391  c.created_before->month(), c.created_before->day());
392  }
393  if (c.is_live.has_value()) {
394  condition["isLive"] = *c.is_live;
395  }
396  if (c.matches_storage_class.has_value()) {
397  condition["matchesStorageClass"] = *c.matches_storage_class;
398  }
399  if (c.num_newer_versions.has_value()) {
400  condition["numNewerVersions"] = *c.num_newer_versions;
401  }
402  nlohmann::json action;
403  if (!a.action().type.empty()) {
404  action["type"] = a.action().type;
405  }
406  if (!a.action().storage_class.empty()) {
407  action["storageClass"] = a.action().storage_class;
408  }
409  array.emplace_back(nlohmann::json{
410  {"action", action},
411  {"condition", condition},
412  });
413  }
414  subpatch.SetArrayField("rule", array.dump());
415  impl_.AddSubPatch("lifecycle", subpatch);
416  return *this;
417 }
418 
420  impl_.RemoveField("lifecycle");
421  return *this;
422 }
423 
425  BucketLogging const& v) {
426  impl_.AddSubPatch(
427  "logging", internal::PatchBuilder()
428  .SetStringField("logBucket", v.log_bucket)
429  .SetStringField("logObjectPrefix", v.log_object_prefix));
430  return *this;
431 }
432 
434  impl_.RemoveField("logging");
435  return *this;
436 }
437 
439  std::string const& v) {
440  if (v.empty()) {
441  return ResetName();
442  }
443  impl_.SetStringField("name", v);
444  return *this;
445 }
446 
448  impl_.RemoveField("name");
449  return *this;
450 }
451 
453  BucketRetentionPolicy const& v) {
454  // Only the retentionPeriod field is writeable, so do not modify the other
455  // fields.
456  impl_.AddSubPatch("retentionPolicy",
457  internal::PatchBuilder().SetIntField(
458  "retentionPeriod", static_cast<std::uint64_t>(
459  v.retention_period.count())));
460  return *this;
461 }
462 
464  impl_.RemoveField("retentionPolicy");
465  return *this;
466 }
467 
469  std::string const& v) {
470  if (v.empty()) return ResetRpo();
471  impl_.SetStringField("rpo", v);
472  return *this;
473 }
474 
476  impl_.RemoveField("rpo");
477  return *this;
478 }
479 
481  std::string const& v) {
482  if (v.empty()) {
483  return ResetStorageClass();
484  }
485  impl_.SetStringField("storageClass", v);
486  return *this;
487 }
488 
490  impl_.RemoveField("storageClass");
491  return *this;
492 }
493 
495  BucketVersioning const& v) {
496  impl_.AddSubPatch("versioning", internal::PatchBuilder().SetBoolField(
497  "enabled", v.enabled));
498  return *this;
499 }
500 
502  impl_.RemoveField("versioning");
503  return *this;
504 }
505 
507  BucketWebsite const& v) {
508  impl_.AddSubPatch("website",
509  internal::PatchBuilder()
510  .SetStringField("mainPageSuffix", v.main_page_suffix)
511  .SetStringField("notFoundPage", v.not_found_page));
512  return *this;
513 }
514 
516  impl_.RemoveField("website");
517  return *this;
518 }
519 
521 } // namespace storage
522 } // namespace cloud
523 } // namespace google