Google Cloud Spanner C++ Client  1.33.0
A C++ Client Library for Google Cloud Spanner
instance_admin_connection.cc
Go to the documentation of this file.
1 // Copyright 2019 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 // TODO(#7356): Remove this file after the deprecation period expires
16 #include "google/cloud/internal/disable_deprecation_warnings.inc"
17 #include "google/cloud/spanner/instance_admin_connection.h"
18 #include "google/cloud/spanner/instance.h"
19 #include "google/cloud/spanner/internal/defaults.h"
20 #include "google/cloud/spanner/options.h"
21 #include "google/cloud/internal/async_long_running_operation.h"
22 #include "google/cloud/internal/retry_loop.h"
23 #include <grpcpp/grpcpp.h>
24 #include <chrono>
25 
26 namespace google {
27 namespace cloud {
28 namespace spanner {
30 
31 namespace gcsa = ::google::spanner::admin::instance::v1;
32 namespace giam = ::google::iam::v1;
33 using ::google::cloud::internal::Idempotency;
34 
35 namespace {
36 
37 class InstanceAdminConnectionImpl : public InstanceAdminConnection {
38  public:
39  InstanceAdminConnectionImpl(
40  std::shared_ptr<spanner_internal::InstanceAdminStub> stub,
41  Options const& opts)
42  : stub_(std::move(stub)),
43  retry_policy_prototype_(opts.get<SpannerRetryPolicyOption>()->clone()),
44  backoff_policy_prototype_(
46  polling_policy_prototype_(
48  background_threads_(internal::MakeBackgroundThreadsFactory(opts)()) {}
49 
50  ~InstanceAdminConnectionImpl() override = default;
51 
52  StatusOr<gcsa::Instance> GetInstance(GetInstanceParams gip) override {
53  gcsa::GetInstanceRequest request;
54  request.set_name(std::move(gip.instance_name));
55  return RetryLoop(
56  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
57  Idempotency::kIdempotent,
58  [this](grpc::ClientContext& context,
59  gcsa::GetInstanceRequest const& request) {
60  return stub_->GetInstance(context, request);
61  },
62  request, __func__);
63  }
64 
65  future<StatusOr<gcsa::Instance>> CreateInstance(
66  CreateInstanceParams p) override {
67  auto stub = stub_;
68  return google::cloud::internal::AsyncLongRunningOperation<gcsa::Instance>(
69  background_threads_->cq(), std::move(p.request),
70  [stub](google::cloud::CompletionQueue& cq,
71  std::unique_ptr<grpc::ClientContext> context,
72  gcsa::CreateInstanceRequest const& request) {
73  return stub->AsyncCreateInstance(cq, std::move(context), request);
74  },
75  [stub](google::cloud::CompletionQueue& cq,
76  std::unique_ptr<grpc::ClientContext> context,
77  google::longrunning::GetOperationRequest const& request) {
78  return stub->AsyncGetOperation(cq, std::move(context), request);
79  },
80  [stub](google::cloud::CompletionQueue& cq,
81  std::unique_ptr<grpc::ClientContext> context,
82  google::longrunning::CancelOperationRequest const& request) {
83  return stub->AsyncCancelOperation(cq, std::move(context), request);
84  },
85  &google::cloud::internal::ExtractLongRunningResultResponse<
86  gcsa::Instance>,
87  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
88  Idempotency::kNonIdempotent, polling_policy_prototype_->clone(),
89  __func__);
90  }
91 
92  future<StatusOr<gcsa::Instance>> UpdateInstance(
93  UpdateInstanceParams p) override {
94  auto stub = stub_;
95  return google::cloud::internal::AsyncLongRunningOperation<gcsa::Instance>(
96  background_threads_->cq(), std::move(p.request),
97  [stub](google::cloud::CompletionQueue& cq,
98  std::unique_ptr<grpc::ClientContext> context,
99  gcsa::UpdateInstanceRequest const& request) {
100  return stub->AsyncUpdateInstance(cq, std::move(context), request);
101  },
102  [stub](google::cloud::CompletionQueue& cq,
103  std::unique_ptr<grpc::ClientContext> context,
104  google::longrunning::GetOperationRequest const& request) {
105  return stub->AsyncGetOperation(cq, std::move(context), request);
106  },
107  [stub](google::cloud::CompletionQueue& cq,
108  std::unique_ptr<grpc::ClientContext> context,
109  google::longrunning::CancelOperationRequest const& request) {
110  return stub->AsyncCancelOperation(cq, std::move(context), request);
111  },
112  &google::cloud::internal::ExtractLongRunningResultResponse<
113  gcsa::Instance>,
114  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
115  Idempotency::kIdempotent, polling_policy_prototype_->clone(), __func__);
116  }
117 
118  Status DeleteInstance(DeleteInstanceParams p) override {
119  gcsa::DeleteInstanceRequest request;
120  request.set_name(std::move(p.instance_name));
121  return RetryLoop(
122  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
123  Idempotency::kIdempotent,
124  [this](grpc::ClientContext& context,
125  gcsa::DeleteInstanceRequest const& request) {
126  return stub_->DeleteInstance(context, request);
127  },
128  request, __func__);
129  }
130 
131  StatusOr<gcsa::InstanceConfig> GetInstanceConfig(
132  GetInstanceConfigParams p) override {
133  gcsa::GetInstanceConfigRequest request;
134  request.set_name(std::move(p.instance_config_name));
135  return RetryLoop(
136  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
137  Idempotency::kIdempotent,
138  [this](grpc::ClientContext& context,
139  gcsa::GetInstanceConfigRequest const& request) {
140  return stub_->GetInstanceConfig(context, request);
141  },
142  request, __func__);
143  }
144 
145  ListInstanceConfigsRange ListInstanceConfigs(
146  ListInstanceConfigsParams params) override {
147  gcsa::ListInstanceConfigsRequest request;
148  request.set_parent("projects/" + params.project_id);
149  request.clear_page_token();
150  auto stub = stub_;
151  // Because we do not have C++14 generalized lambda captures we cannot just
152  // use the unique_ptr<> here, so convert to shared_ptr<> instead.
153  auto retry = std::shared_ptr<RetryPolicy>(retry_policy_prototype_->clone());
154  auto backoff =
155  std::shared_ptr<BackoffPolicy>(backoff_policy_prototype_->clone());
156 
157  char const* function_name = __func__;
158  return google::cloud::internal::MakePaginationRange<
159  ListInstanceConfigsRange>(
160  std::move(request),
161  [stub, retry, backoff,
162  function_name](gcsa::ListInstanceConfigsRequest const& r) {
163  return RetryLoop(
164  retry->clone(), backoff->clone(), Idempotency::kIdempotent,
165  [stub](grpc::ClientContext& context,
166  gcsa::ListInstanceConfigsRequest const& request) {
167  return stub->ListInstanceConfigs(context, request);
168  },
169  r, function_name);
170  },
171  [](gcsa::ListInstanceConfigsResponse r) {
172  std::vector<gcsa::InstanceConfig> result(r.instance_configs().size());
173  auto& configs = *r.mutable_instance_configs();
174  std::move(configs.begin(), configs.end(), result.begin());
175  return result;
176  });
177  }
178 
179  ListInstancesRange ListInstances(ListInstancesParams params) override {
180  gcsa::ListInstancesRequest request;
181  request.set_parent("projects/" + params.project_id);
182  request.set_filter(std::move(params.filter));
183  request.clear_page_token();
184  auto stub = stub_;
185  // Because we do not have C++14 generalized lambda captures we cannot just
186  // use the unique_ptr<> here, so convert to shared_ptr<> instead.
187  auto retry = std::shared_ptr<RetryPolicy>(retry_policy_prototype_->clone());
188  auto backoff =
189  std::shared_ptr<BackoffPolicy>(backoff_policy_prototype_->clone());
190 
191  char const* function_name = __func__;
192  return google::cloud::internal::MakePaginationRange<ListInstancesRange>(
193  std::move(request),
194  [stub, retry, backoff,
195  function_name](gcsa::ListInstancesRequest const& r) {
196  return RetryLoop(
197  retry->clone(), backoff->clone(), Idempotency::kIdempotent,
198  [stub](grpc::ClientContext& context,
199  gcsa::ListInstancesRequest const& request) {
200  return stub->ListInstances(context, request);
201  },
202  r, function_name);
203  },
204  [](gcsa::ListInstancesResponse r) {
205  std::vector<gcsa::Instance> result(r.instances().size());
206  auto& instances = *r.mutable_instances();
207  std::move(instances.begin(), instances.end(), result.begin());
208  return result;
209  });
210  }
211 
212  StatusOr<giam::Policy> GetIamPolicy(GetIamPolicyParams p) override {
213  google::iam::v1::GetIamPolicyRequest request;
214  request.set_resource(std::move(p.instance_name));
215  return RetryLoop(
216  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
217  Idempotency::kIdempotent,
218  [this](grpc::ClientContext& context,
219  giam::GetIamPolicyRequest const& request) {
220  return stub_->GetIamPolicy(context, request);
221  },
222  request, __func__);
223  }
224 
225  StatusOr<giam::Policy> SetIamPolicy(SetIamPolicyParams p) override {
226  google::iam::v1::SetIamPolicyRequest request;
227  request.set_resource(std::move(p.instance_name));
228  *request.mutable_policy() = std::move(p.policy);
229  auto const idempotency = request.policy().etag().empty()
230  ? Idempotency::kNonIdempotent
231  : Idempotency::kIdempotent;
232  return RetryLoop(
233  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
234  idempotency,
235  [this](grpc::ClientContext& context,
236  giam::SetIamPolicyRequest const& request) {
237  return stub_->SetIamPolicy(context, request);
238  },
239  request, __func__);
240  }
241 
242  StatusOr<google::iam::v1::TestIamPermissionsResponse> TestIamPermissions(
243  TestIamPermissionsParams p) override {
244  google::iam::v1::TestIamPermissionsRequest request;
245  request.set_resource(std::move(p.instance_name));
246  for (auto& permission : p.permissions) {
247  request.add_permissions(std::move(permission));
248  }
249  return RetryLoop(
250  retry_policy_prototype_->clone(), backoff_policy_prototype_->clone(),
251  Idempotency::kIdempotent,
252  [this](grpc::ClientContext& context,
253  giam::TestIamPermissionsRequest const& request) {
254  return stub_->TestIamPermissions(context, request);
255  },
256  request, __func__);
257  }
258 
259  private:
260  std::shared_ptr<spanner_internal::InstanceAdminStub> stub_;
261  std::unique_ptr<RetryPolicy const> retry_policy_prototype_;
262  std::unique_ptr<BackoffPolicy const> backoff_policy_prototype_;
263  std::unique_ptr<PollingPolicy const> polling_policy_prototype_;
264 
265  // Implementations of `BackgroundThreads` typically create a pool of
266  // threads that are joined during destruction, so, to avoid ownership
267  // cycles, those threads should never assume ownership of this object
268  // (e.g., via a `std::shared_ptr<>`).
269  std::unique_ptr<BackgroundThreads> background_threads_;
270 };
271 
272 } // namespace
273 
275 
277  Options opts) {
278  internal::CheckExpectedOptions<CommonOptionList, GrpcOptionList,
279  SpannerPolicyOptionList>(opts, __func__);
280  opts = spanner_internal::DefaultAdminOptions(std::move(opts));
281  auto stub = spanner_internal::CreateDefaultInstanceAdminStub(opts);
282  return std::make_shared<spanner::InstanceAdminConnectionImpl>(
283  std::move(stub), std::move(opts));
284 }
285 
287  ConnectionOptions const& options) {
288  return MakeInstanceAdminConnection(internal::MakeOptions(options));
289 }
290 
292  ConnectionOptions const& options, std::unique_ptr<RetryPolicy> retry_policy,
293  std::unique_ptr<BackoffPolicy> backoff_policy,
294  std::unique_ptr<PollingPolicy> polling_policy) {
295  auto opts = internal::MakeOptions(options);
296  opts.set<SpannerRetryPolicyOption>(std::move(retry_policy));
297  opts.set<SpannerBackoffPolicyOption>(std::move(backoff_policy));
298  opts.set<SpannerPollingPolicyOption>(std::move(polling_policy));
299  return MakeInstanceAdminConnection(std::move(opts));
300 }
301 
303 } // namespace spanner
304 
305 namespace spanner_internal {
307 
308 std::shared_ptr<spanner::InstanceAdminConnection>
309 MakeInstanceAdminConnectionForTesting(std::shared_ptr<InstanceAdminStub> stub,
310  Options opts) {
311  opts = spanner_internal::DefaultAdminOptions(std::move(opts));
312  return std::make_shared<spanner::InstanceAdminConnectionImpl>(
313  std::move(stub), std::move(opts));
314 }
315 
317 } // namespace spanner_internal
318 } // namespace cloud
319 } // namespace google