Google Cloud Storage C++ Client  1.32.1
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 {
30 inline namespace STORAGE_CLIENT_NS {
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()) return pap;
37  if (*pap == PublicAccessPreventionUnspecified()) return *normalized;
38  return pap;
39 }
40 } // namespace internal
41 
42 std::ostream& operator<<(std::ostream& os, CorsEntry const& rhs) {
43  os << "CorsEntry={";
44  char const* sep = "";
45  if (rhs.max_age_seconds.has_value()) {
46  os << sep << "max_age_seconds=" << *rhs.max_age_seconds;
47  sep = ", ";
48  }
49  return os << sep << "method=[" << absl::StrJoin(rhs.method, ", ")
50  << "], origin=[" << absl::StrJoin(rhs.origin, ", ")
51  << "], response_header=["
52  << absl::StrJoin(rhs.response_header, ", ") << "]}";
53 }
54 
55 std::ostream& operator<<(std::ostream& os,
56  UniformBucketLevelAccess const& rhs) {
57  google::cloud::internal::IosFlagsSaver save_format(os);
58  return os << "UniformBucketLevelAccess={enabled=" << std::boolalpha
59  << rhs.enabled << ", locked_time="
60  << google::cloud::internal::FormatRfc3339(rhs.locked_time) << "}";
61 }
62 
63 std::ostream& operator<<(std::ostream& os, BucketIamConfiguration const& rhs) {
64  os << "BucketIamConfiguration={";
65  char const* sep = "";
66  if (rhs.public_access_prevention.has_value()) {
67  os << sep << "public_access_prevention=" << *rhs.public_access_prevention;
68  sep = ", ";
69  }
70  if (rhs.uniform_bucket_level_access.has_value()) {
71  os << sep
72  << "uniform_bucket_level_access=" << *rhs.uniform_bucket_level_access;
73  return os << "}";
74  }
75  return os << "}";
76 }
77 
78 std::ostream& operator<<(std::ostream& os, BucketLogging const& rhs) {
79  return os << "BucketLogging={log_bucket=" << rhs.log_bucket
80  << ", log_object_prefix=" << rhs.log_object_prefix << "}";
81 }
82 
83 std::ostream& operator<<(std::ostream& os, BucketRetentionPolicy const& rhs) {
84  return os << "BucketRetentionPolicy={retention_period="
85  << rhs.retention_period.count() << "s, effective_time="
86  << google::cloud::internal::FormatRfc3339(rhs.effective_time)
87  << ", locked=" << rhs.is_locked << "}";
88 }
89 
90 bool operator==(BucketMetadata const& lhs, BucketMetadata const& rhs) {
91  return static_cast<internal::CommonMetadata<BucketMetadata> const&>(lhs) ==
92  rhs &&
93  lhs.acl_ == rhs.acl_ && lhs.billing_ == rhs.billing_ &&
94  lhs.cors_ == rhs.cors_ &&
95  lhs.default_event_based_hold_ == rhs.default_event_based_hold_ &&
96  lhs.default_acl_ == rhs.default_acl_ &&
97  lhs.encryption_ == rhs.encryption_ &&
98  lhs.iam_configuration_ == rhs.iam_configuration_ &&
99  lhs.project_number_ == rhs.project_number_ &&
100  lhs.lifecycle_ == rhs.lifecycle_ && lhs.location_ == rhs.location_ &&
101  lhs.location_type_ == rhs.location_type_ &&
102  lhs.logging_ == rhs.logging_ && lhs.labels_ == rhs.labels_ &&
103  lhs.retention_policy_ == rhs.retention_policy_ &&
104  lhs.versioning_ == rhs.versioning_ && 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  if (rhs.versioning().has_value()) {
188  auto previous_flags = os.flags();
189  os << ", versioning.enabled=" << std::boolalpha
190  << rhs.versioning()->enabled;
191  os.flags(previous_flags);
192  }
193 
194  if (rhs.has_website()) {
195  os << ", website.main_page_suffix=" << rhs.website().main_page_suffix
196  << ", website.not_found_page=" << rhs.website().not_found_page;
197  }
198 
199  return os << "}";
200 }
201 
203  internal::PatchBuilder tmp = impl_;
204  if (labels_subpatch_dirty_) {
205  if (labels_subpatch_.empty()) {
206  tmp.RemoveField("labels");
207  } else {
208  tmp.AddSubPatch("labels", labels_subpatch_);
209  }
210  }
211  return tmp.ToString();
212 }
213 
215  std::vector<BucketAccessControl> const& v) {
216  if (v.empty()) {
217  return ResetAcl();
218  }
219  auto array = nlohmann::json::array();
220  for (auto const& a : v) {
221  array.emplace_back(nlohmann::json{
222  {"entity", a.entity()},
223  {"role", a.role()},
224  });
225  }
226  impl_.SetArrayField("acl", array.dump());
227  return *this;
228 }
229 
231  impl_.RemoveField("acl");
232  return *this;
233 }
234 
236  BucketBilling const& v) {
237  impl_.AddSubPatch("billing", internal::PatchBuilder().SetBoolField(
238  "requesterPays", v.requester_pays));
239  return *this;
240 }
241 
243  impl_.RemoveField("billing");
244  return *this;
245 }
246 
248  std::vector<CorsEntry> const& v) {
249  if (v.empty()) {
250  return ResetCors();
251  }
252  auto array = nlohmann::json::array();
253  for (auto const& a : v) {
254  nlohmann::json entry;
255  if (a.max_age_seconds.has_value()) {
256  entry["maxAgeSeconds"] = *a.max_age_seconds;
257  }
258  if (!a.method.empty()) {
259  entry["method"] = a.method;
260  }
261  if (!a.origin.empty()) {
262  entry["origin"] = a.origin;
263  }
264  if (!a.response_header.empty()) {
265  entry["responseHeader"] = a.response_header;
266  }
267  array.emplace_back(std::move(entry));
268  }
269  impl_.SetArrayField("cors", array.dump());
270  return *this;
271 }
272 
274  impl_.RemoveField("cors");
275  return *this;
276 }
277 
280  impl_.SetBoolField("defaultEventBasedHold", v);
281  return *this;
282 }
283 
286  impl_.RemoveField("defaultEventBasedHold");
287  return *this;
288 }
289 
291  std::vector<ObjectAccessControl> const& v) {
292  if (v.empty()) {
293  return ResetDefaultAcl();
294  }
295  auto array = nlohmann::json::array();
296  for (auto const& a : v) {
297  array.emplace_back(nlohmann::json{
298  {"entity", a.entity()},
299  {"role", a.role()},
300  });
301  }
302  impl_.SetArrayField("defaultObjectAcl", array.dump());
303  return *this;
304 }
305 
307  impl_.RemoveField("defaultObjectAcl");
308  return *this;
309 }
310 
312  BucketEncryption const& v) {
313  impl_.AddSubPatch("encryption",
314  internal::PatchBuilder().SetStringField(
315  "defaultKmsKeyName", v.default_kms_key_name));
316  return *this;
317 }
318 
320  impl_.RemoveField("encryption");
321  return *this;
322 }
323 
325  BucketIamConfiguration const& v) {
326  internal::PatchBuilder iam_configuration;
327 
328  if (v.public_access_prevention.has_value()) {
329  iam_configuration.SetStringField("publicAccessPrevention",
331  }
332  if (v.uniform_bucket_level_access.has_value()) {
333  internal::PatchBuilder uniform_bucket_level_access;
334  uniform_bucket_level_access.SetBoolField(
336  // The lockedTime field should not be set, this is not a mutable field, it
337  // is set by the server when the policy is enabled.
338  iam_configuration.AddSubPatch("uniformBucketLevelAccess",
339  uniform_bucket_level_access);
340  impl_.AddSubPatch("iamConfiguration", iam_configuration);
341  return *this;
342  }
343  impl_.AddSubPatch("iamConfiguration", iam_configuration);
344  return *this;
345 }
346 
349  impl_.RemoveField("iamConfiguration");
350  return *this;
351 }
352 
354  std::string const& label, std::string const& value) {
355  labels_subpatch_.SetStringField(label.c_str(), value);
356  labels_subpatch_dirty_ = true;
357  return *this;
358 }
359 
361  std::string const& label) {
362  labels_subpatch_.RemoveField(label.c_str());
363  labels_subpatch_dirty_ = true;
364  return *this;
365 }
366 
368  labels_subpatch_.clear();
369  labels_subpatch_dirty_ = true;
370  return *this;
371 }
372 
374  BucketLifecycle const& v) {
375  if (v.rule.empty()) {
376  return ResetLifecycle();
377  }
378  internal::PatchBuilder subpatch;
379  auto array = nlohmann::json::array();
380  for (auto const& a : v.rule) {
381  nlohmann::json condition;
382  auto const& c = a.condition();
383  if (c.age.has_value()) {
384  condition["age"] = *c.age;
385  }
386  if (c.created_before.has_value()) {
387  condition["createdBefore"] =
388  absl::StrFormat("%04d-%02d-%02d", c.created_before->year(),
389  c.created_before->month(), c.created_before->day());
390  }
391  if (c.is_live.has_value()) {
392  condition["isLive"] = *c.is_live;
393  }
394  if (c.matches_storage_class.has_value()) {
395  condition["matchesStorageClass"] = *c.matches_storage_class;
396  }
397  if (c.num_newer_versions.has_value()) {
398  condition["numNewerVersions"] = *c.num_newer_versions;
399  }
400  nlohmann::json action;
401  if (!a.action().type.empty()) {
402  action["type"] = a.action().type;
403  }
404  if (!a.action().storage_class.empty()) {
405  action["storageClass"] = a.action().storage_class;
406  }
407  array.emplace_back(nlohmann::json{
408  {"action", action},
409  {"condition", condition},
410  });
411  }
412  subpatch.SetArrayField("rule", array.dump());
413  impl_.AddSubPatch("lifecycle", subpatch);
414  return *this;
415 }
416 
418  impl_.RemoveField("lifecycle");
419  return *this;
420 }
421 
423  BucketLogging const& v) {
424  impl_.AddSubPatch(
425  "logging", internal::PatchBuilder()
426  .SetStringField("logBucket", v.log_bucket)
427  .SetStringField("logObjectPrefix", v.log_object_prefix));
428  return *this;
429 }
430 
432  impl_.RemoveField("logging");
433  return *this;
434 }
435 
437  std::string const& v) {
438  if (v.empty()) {
439  return ResetName();
440  }
441  impl_.SetStringField("name", v);
442  return *this;
443 }
444 
446  impl_.RemoveField("name");
447  return *this;
448 }
449 
451  BucketRetentionPolicy const& v) {
452  // Only the retentionPeriod field is writeable, so do not modify the other
453  // fields.
454  impl_.AddSubPatch("retentionPolicy",
455  internal::PatchBuilder().SetIntField(
456  "retentionPeriod", static_cast<std::uint64_t>(
457  v.retention_period.count())));
458  return *this;
459 }
460 
462  impl_.RemoveField("retentionPolicy");
463  return *this;
464 }
465 
467  std::string const& v) {
468  if (v.empty()) {
469  return ResetStorageClass();
470  }
471  impl_.SetStringField("storageClass", v);
472  return *this;
473 }
474 
476  impl_.RemoveField("storageClass");
477  return *this;
478 }
479 
481  BucketVersioning const& v) {
482  impl_.AddSubPatch("versioning", internal::PatchBuilder().SetBoolField(
483  "enabled", v.enabled));
484  return *this;
485 }
486 
488  impl_.RemoveField("versioning");
489  return *this;
490 }
491 
493  BucketWebsite const& v) {
494  impl_.AddSubPatch("website",
495  internal::PatchBuilder()
496  .SetStringField("mainPageSuffix", v.main_page_suffix)
497  .SetStringField("notFoundPage", v.not_found_page));
498  return *this;
499 }
500 
502  impl_.RemoveField("website");
503  return *this;
504 }
505 
506 } // namespace STORAGE_CLIENT_NS
507 } // namespace storage
508 } // namespace cloud
509 } // namespace google