Skip to content

Commit 93c8274

Browse files
authored
feat(storage): add support for bucket metadata call in async client (googleapis#16262)
1 parent 6935c82 commit 93c8274

31 files changed

Lines changed: 484 additions & 0 deletions
-1 Bytes
Binary file not shown.
33.4 KB
Binary file not shown.

generator/generator_config.textproto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3905,6 +3905,7 @@ service {
39053905
gen_async_rpcs: [
39063906
"ComposeObject",
39073907
"DeleteObject",
3908+
"GetBucket",
39083909
"ReadObject",
39093910
"RewriteObject",
39103911
"StartResumableWrite",

google/cloud/storage/async/client.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ AsyncClient::AsyncClient(Options options) {
4141
AsyncClient::AsyncClient(std::shared_ptr<AsyncConnection> connection)
4242
: connection_(std::move(connection)) {}
4343

44+
future<StatusOr<google::storage::v2::Bucket>> AsyncClient::GetBucket(
45+
BucketName const& bucket_name, Options opts) {
46+
auto request = google::storage::v2::GetBucketRequest{};
47+
request.set_name(bucket_name.FullName());
48+
return GetBucket(std::move(request), std::move(opts));
49+
}
50+
51+
future<StatusOr<google::storage::v2::Bucket>> AsyncClient::GetBucket(
52+
google::storage::v2::GetBucketRequest request, Options opts) {
53+
return connection_->GetBucket(
54+
{std::move(request), google::cloud::internal::MergeOptions(
55+
std::move(opts), connection_->options())});
56+
}
57+
4458
future<StatusOr<google::storage::v2::Object>> AsyncClient::InsertObject(
4559
google::storage::v2::WriteObjectRequest request, WritePayload contents,
4660
Options opts) {

google/cloud/storage/async/client.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,36 @@ class AsyncClient {
9090

9191
~AsyncClient() = default;
9292

93+
/**
94+
* Get bucket metadata.
95+
*
96+
* @par Example
97+
* @snippet storage_async_samples.cc get-bucket
98+
*
99+
* @par Idempotency
100+
* This is a read-only operation and is always idempotent.
101+
*
102+
* @param bucket_name the name of the bucket to get metadata for.
103+
* @param opts options controlling the behavior of this RPC.
104+
*/
105+
future<StatusOr<google::storage::v2::Bucket>> GetBucket(
106+
BucketName const& bucket_name, Options opts = {});
107+
108+
/**
109+
* Get bucket metadata using a raw request.
110+
*
111+
* @par Example
112+
* @snippet storage_async_samples.cc get-bucket
113+
*
114+
* @par Idempotency
115+
* This is a read-only operation and is always idempotent.
116+
*
117+
* @param request the request contents.
118+
* @param opts options controlling the behavior of this RPC.
119+
*/
120+
future<StatusOr<google::storage::v2::Bucket>> GetBucket(
121+
google::storage::v2::GetBucketRequest request, Options opts = {});
122+
93123
/*
94124
This snippet discusses the tradeoffs between `InsertObject()`,
95125
`StartBufferedUpload()`, and `StartUnbufferedUpload()`. The text is included

google/cloud/storage/async/client_test.cc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,76 @@ auto TestProtoObject() {
6161
return result;
6262
}
6363

64+
auto TestProtoBucket() {
65+
google::storage::v2::Bucket result;
66+
result.set_name("projects/_/buckets/test-bucket");
67+
return result;
68+
}
69+
70+
TEST(AsyncClient, GetBucket1) {
71+
auto constexpr kExpectedRequest = R"pb(
72+
name: "projects/_/buckets/test-bucket"
73+
)pb";
74+
auto mock = std::make_shared<MockAsyncConnection>();
75+
EXPECT_CALL(*mock, options)
76+
.WillRepeatedly(
77+
Return(Options{}.set<TestOption<0>>("O0").set<TestOption<1>>("O1")));
78+
79+
EXPECT_CALL(*mock, GetBucket)
80+
.WillOnce([&](AsyncConnection::GetBucketParams const& p) {
81+
EXPECT_THAT(p.options.get<TestOption<0>>(), "O0");
82+
EXPECT_THAT(p.options.get<TestOption<1>>(), "O1-function");
83+
EXPECT_THAT(p.options.get<TestOption<2>>(), "O2-function");
84+
auto expected = google::storage::v2::GetBucketRequest{};
85+
EXPECT_TRUE(TextFormat::ParseFromString(kExpectedRequest, &expected));
86+
EXPECT_THAT(p.request, IsProtoEqual(expected));
87+
return make_ready_future(make_status_or(TestProtoBucket()));
88+
});
89+
90+
auto client = AsyncClient(mock);
91+
auto response = client
92+
.GetBucket(BucketName("test-bucket"),
93+
Options{}
94+
.set<TestOption<1>>("O1-function")
95+
.set<TestOption<2>>("O2-function"))
96+
.get();
97+
ASSERT_STATUS_OK(response);
98+
EXPECT_THAT(*response, IsProtoEqual(TestProtoBucket()));
99+
}
100+
101+
TEST(AsyncClient, GetBucket2) {
102+
auto constexpr kExpectedRequest = R"pb(
103+
name: "projects/_/buckets/test-bucket"
104+
)pb";
105+
auto mock = std::make_shared<MockAsyncConnection>();
106+
EXPECT_CALL(*mock, options)
107+
.WillRepeatedly(
108+
Return(Options{}.set<TestOption<0>>("O0").set<TestOption<1>>("O1")));
109+
110+
EXPECT_CALL(*mock, GetBucket)
111+
.WillOnce([&](AsyncConnection::GetBucketParams const& p) {
112+
EXPECT_THAT(p.options.get<TestOption<0>>(), "O0");
113+
EXPECT_THAT(p.options.get<TestOption<1>>(), "O1-function");
114+
EXPECT_THAT(p.options.get<TestOption<2>>(), "O2-function");
115+
auto expected = google::storage::v2::GetBucketRequest{};
116+
EXPECT_TRUE(TextFormat::ParseFromString(kExpectedRequest, &expected));
117+
EXPECT_THAT(p.request, IsProtoEqual(expected));
118+
return make_ready_future(make_status_or(TestProtoBucket()));
119+
});
120+
121+
auto request = google::storage::v2::GetBucketRequest{};
122+
request.set_name("projects/_/buckets/test-bucket");
123+
auto client = AsyncClient(mock);
124+
auto response =
125+
client
126+
.GetBucket(std::move(request), Options{}
127+
.set<TestOption<1>>("O1-function")
128+
.set<TestOption<2>>("O2-function"))
129+
.get();
130+
ASSERT_STATUS_OK(response);
131+
EXPECT_THAT(*response, IsProtoEqual(TestProtoBucket()));
132+
}
133+
64134
TEST(AsyncClient, InsertObject1) {
65135
auto constexpr kExpectedRequest = R"pb(
66136
write_object_spec {

google/cloud/storage/async/connection.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ class AsyncConnection {
5454
/// The options used to configure this connection, with any defaults applied.
5555
virtual Options options() const = 0;
5656

57+
/**
58+
* A thin wrapper around the `GetBucket()` parameters.
59+
*
60+
* We use a single struct as the input parameter for this function to
61+
* prevent breaking any mocks when additional parameters are needed.
62+
*/
63+
struct GetBucketParams {
64+
google::storage::v2::GetBucketRequest request;
65+
Options options;
66+
};
67+
68+
/// Get bucket metadata.
69+
virtual future<StatusOr<google::storage::v2::Bucket>> GetBucket(
70+
GetBucketParams p) = 0;
71+
5772
/**
5873
* A thin wrapper around the `InsertObject()` parameters.
5974
*

google/cloud/storage/async/idempotency_policy.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class AlwaysRetryAsyncIdempotencyPolicy : public AsyncIdempotencyPolicy {
3535
return Idempotency::kIdempotent;
3636
}
3737

38+
google::cloud::Idempotency GetBucket(
39+
google::storage::v2::GetBucketRequest const&) override {
40+
return Idempotency::kIdempotent;
41+
}
42+
3843
google::cloud::Idempotency InsertObject(
3944
google::storage::v2::WriteObjectRequest const&) override {
4045
return Idempotency::kIdempotent;
@@ -71,6 +76,12 @@ google::cloud::Idempotency AsyncIdempotencyPolicy::ReadObject(
7176
return Idempotency::kIdempotent;
7277
}
7378

79+
google::cloud::Idempotency AsyncIdempotencyPolicy::GetBucket(
80+
google::storage::v2::GetBucketRequest const&) {
81+
// Read operations are always idempotent.
82+
return Idempotency::kIdempotent;
83+
}
84+
7485
google::cloud::Idempotency AsyncIdempotencyPolicy::InsertObject(
7586
google::storage::v2::WriteObjectRequest const& request) {
7687
auto const& spec = request.write_object_spec();

google/cloud/storage/async/idempotency_policy.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class AsyncIdempotencyPolicy {
6161
virtual google::cloud::Idempotency ReadObject(
6262
google::storage::v2::ReadObjectRequest const&);
6363

64+
/// Determine if a google.storage.v2.GetBucketRequest is idempotent.
65+
virtual google::cloud::Idempotency GetBucket(
66+
google::storage::v2::GetBucketRequest const&);
67+
6468
/// Determine if a google.storage.v2.WriteObjectRequest for a one-shot upload
6569
/// is idempotent.
6670
virtual google::cloud::Idempotency InsertObject(

google/cloud/storage/async/idempotency_policy_test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ TEST(IdempotencyPolicy, Strict) {
3737

3838
EXPECT_EQ(policy->ReadObject(google::storage::v2::ReadObjectRequest{}),
3939
Idempotency::kIdempotent);
40+
EXPECT_EQ(policy->GetBucket(google::storage::v2::GetBucketRequest{}),
41+
Idempotency::kIdempotent);
4042

4143
EXPECT_EQ(policy->InsertObject(google::storage::v2::WriteObjectRequest{}),
4244
Idempotency::kNonIdempotent);
@@ -90,6 +92,8 @@ TEST(IdempotencyPolicy, AlwaysRetry) {
9092
ASSERT_THAT(policy, NotNull());
9193
EXPECT_EQ(policy->ReadObject(google::storage::v2::ReadObjectRequest{}),
9294
Idempotency::kIdempotent);
95+
EXPECT_EQ(policy->GetBucket(google::storage::v2::GetBucketRequest{}),
96+
Idempotency::kIdempotent);
9397
EXPECT_EQ(policy->InsertObject(google::storage::v2::WriteObjectRequest{}),
9498
Idempotency::kIdempotent);
9599
EXPECT_EQ(policy->WriteObject(google::storage::v2::WriteObjectRequest{}),

0 commit comments

Comments
 (0)