1 // Copyright 2020 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/client.h"
16 #include "google/cloud/storage/examples/storage_examples_common.h"
17 #include "google/cloud/internal/getenv.h"
18 #include <functional>
19 #include <iostream>
20 #include <thread>
21 
22 namespace {
23 
GetDefaultEventBasedHold(google::cloud::storage::Client client,std::vector<std::string> const & argv)24 void GetDefaultEventBasedHold(google::cloud::storage::Client client,
25                               std::vector<std::string> const& argv) {
26   //! [get default event based hold]
27   // [START storage_get_default_event_based_hold]
28   namespace gcs = google::cloud::storage;
29   using ::google::cloud::StatusOr;
30   [](gcs::Client client, std::string const& bucket_name) {
31     StatusOr<gcs::BucketMetadata> bucket_metadata =
32         client.GetBucketMetadata(bucket_name);
33 
34     if (!bucket_metadata) {
35       throw std::runtime_error(bucket_metadata.status().message());
36     }
37 
38     std::cout << "The default event-based hold for objects in bucket "
39               << bucket_metadata->name() << " is "
40               << (bucket_metadata->default_event_based_hold() ? "enabled"
41                                                               : "disabled")
42               << "\n";
43   }
44   // [END storage_get_default_event_based_hold]
45   //! [get default event based hold]
46   (std::move(client), argv.at(0));
47 }
48 
EnableDefaultEventBasedHold(google::cloud::storage::Client client,std::vector<std::string> const & argv)49 void EnableDefaultEventBasedHold(google::cloud::storage::Client client,
50                                  std::vector<std::string> const& argv) {
51   //! [enable default event based hold]
52   // [START storage_enable_default_event_based_hold]
53   namespace gcs = google::cloud::storage;
54   using ::google::cloud::StatusOr;
55   [](gcs::Client client, std::string const& bucket_name) {
56     StatusOr<gcs::BucketMetadata> original =
57         client.GetBucketMetadata(bucket_name);
58 
59     if (!original) throw std::runtime_error(original.status().message());
60     StatusOr<gcs::BucketMetadata> patched_metadata = client.PatchBucket(
61         bucket_name,
62         gcs::BucketMetadataPatchBuilder().SetDefaultEventBasedHold(true),
63         gcs::IfMetagenerationMatch(original->metageneration()));
64 
65     if (!patched_metadata) {
66       throw std::runtime_error(patched_metadata.status().message());
67     }
68 
69     std::cout << "The default event-based hold for objects in bucket "
70               << bucket_name << " is "
71               << (patched_metadata->default_event_based_hold() ? "enabled"
72                                                                : "disabled")
73               << "\n";
74   }
75   // [END storage_enable_default_event_based_hold]
76   //! [enable default event based hold]
77   (std::move(client), argv.at(0));
78 }
79 
DisableDefaultEventBasedHold(google::cloud::storage::Client client,std::vector<std::string> const & argv)80 void DisableDefaultEventBasedHold(google::cloud::storage::Client client,
81                                   std::vector<std::string> const& argv) {
82   //! [disable default event based hold]
83   // [START storage_disable_default_event_based_hold]
84   namespace gcs = google::cloud::storage;
85   using ::google::cloud::StatusOr;
86   [](gcs::Client client, std::string const& bucket_name) {
87     StatusOr<gcs::BucketMetadata> original =
88         client.GetBucketMetadata(bucket_name);
89 
90     if (!original) throw std::runtime_error(original.status().message());
91     StatusOr<gcs::BucketMetadata> patched_metadata = client.PatchBucket(
92         bucket_name,
93         gcs::BucketMetadataPatchBuilder().SetDefaultEventBasedHold(false),
94         gcs::IfMetagenerationMatch(original->metageneration()));
95 
96     if (!patched_metadata) {
97       throw std::runtime_error(patched_metadata.status().message());
98     }
99 
100     std::cout << "The default event-based hold for objects in bucket "
101               << bucket_name << " is "
102               << (patched_metadata->default_event_based_hold() ? "enabled"
103                                                                : "disabled")
104               << "\n";
105   }
106   // [END storage_disable_default_event_based_hold]
107   //! [disable default event based hold]
108   (std::move(client), argv.at(0));
109 }
110 
RunAll(std::vector<std::string> const & argv)111 void RunAll(std::vector<std::string> const& argv) {
112   namespace examples = ::google::cloud::storage::examples;
113   namespace gcs = ::google::cloud::storage;
114 
115   if (!argv.empty()) throw examples::Usage{"auto"};
116   examples::CheckEnvironmentVariablesAreSet({
117       "GOOGLE_CLOUD_PROJECT",
118   });
119   auto const project_id =
120       google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value();
121   auto generator = google::cloud::internal::DefaultPRNG(std::random_device{}());
122   auto const bucket_name =
123       examples::MakeRandomBucketName(generator, "cloud-cpp-test-examples-");
124   auto client = gcs::Client::CreateDefaultClient().value();
125 
126   std::cout << "\nCreating bucket to run the examples" << std::endl;
127   (void)client.CreateBucketForProject(bucket_name, project_id,
128                                       gcs::BucketMetadata{});
129   // In GCS a single project cannot create or delete buckets more often than
130   // once every two seconds. We will pause until that time before deleting the
131   // bucket.
132   auto pause = std::chrono::steady_clock::now() + std::chrono::seconds(2);
133 
134   std::cout << "\nRunning GetDefaultEventBasedHold() example" << std::endl;
135   GetDefaultEventBasedHold(client, {bucket_name});
136 
137   std::cout << "\nRunning EnableDefaultEventBasedHold() example" << std::endl;
138   EnableDefaultEventBasedHold(client, {bucket_name});
139 
140   std::cout << "\nRunning DisableDefaultEventBasedHold() example" << std::endl;
141   DisableDefaultEventBasedHold(client, {bucket_name});
142 
143   std::cout << "\nCleaning up" << std::endl;
144   if (!examples::UsingTestbench()) std::this_thread::sleep_until(pause);
145   (void)client.DeleteBucket(bucket_name);
146 }
147 
148 }  // anonymous namespace
149 
main(int argc,char * argv[])150 int main(int argc, char* argv[]) {
151   namespace examples = ::google::cloud::storage::examples;
152   auto make_entry = [](std::string const& name,
153                        std::vector<std::string> arg_names,
154                        examples::ClientCommand const& cmd) {
155     arg_names.insert(arg_names.begin(), "<bucket-name>");
156     return examples::CreateCommandEntry(name, std::move(arg_names), cmd);
157   };
158 
159   examples::Example example({
160       make_entry("get-default-event-based-hold", {}, GetDefaultEventBasedHold),
161       make_entry("enable-default-event-based-hold", {},
162                  EnableDefaultEventBasedHold),
163       make_entry("disable-default-event-based-hold", {},
164                  DisableDefaultEventBasedHold),
165       {"auto", RunAll},
166   });
167   return example.Run(argc, argv);
168 }
169