Skip to content

Commit a5dacb7

Browse files
authored
Implement Client::ListBuckets() without project. (#942)
This fixes #898. It adds a default project to ClientOptions, and uses that project in ListBuckets. Because of the parameter packs, the function to take an explicit project id is now called Client::ListBucketsForProject. * Address review comments [skip ci]. * Address review comments.
1 parent ed6f7f8 commit a5dacb7

File tree

7 files changed

+100
-11
lines changed

7 files changed

+100
-11
lines changed

google/cloud/storage/client.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,48 @@ class Client {
7171
* @throw std::runtime_error if the operation fails.
7272
*
7373
* @par Example
74-
* @snippet storage_bucket_samples.cc list buckets
74+
* @snippet storage_bucket_samples.cc list buckets for project
7575
*/
7676
template <typename... Options>
77-
ListBucketsReader ListBuckets(std::string const& project_id,
78-
Options&&... options) {
77+
ListBucketsReader ListBucketsForProject(std::string const& project_id,
78+
Options&&... options) {
7979
return ListBucketsReader(raw_client_, project_id,
8080
std::forward<Options>(options)...);
8181
}
8282

8383
/**
84-
* Fetch the bucket metadata and return it.c
84+
* Fetch the list of buckets for the default project.
85+
*
86+
* The default project is configured in the `ClientOptions` used to construct
87+
* this object. If the application does not set the project id in the
88+
* `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is used. If
89+
* neither the environment variable is set, nor a value is set explicitly by
90+
* the application this function raises an exception.
91+
*
92+
* @param options a list of optional query parameters and/or request headers.
93+
* Valid types for this operation include `MaxResults`, `Prefix`,
94+
* `UserProject`, and `Projection`.
95+
*
96+
* @throw std::logic_error if the function is called without a default
97+
* project id set.
98+
* @throw std::runtime_error if the operation fails.
99+
*
100+
* @par Example
101+
* @snippet storage_bucket_samples.cc list buckets
102+
*/
103+
template <typename... Options>
104+
ListBucketsReader ListBuckets(Options&&... options) {
105+
auto const& project_id = raw_client_->client_options().project_id();
106+
if (project_id.empty()) {
107+
std::string msg = "Default project id not set in ";
108+
msg += __func__;
109+
google::cloud::internal::RaiseLogicError(msg);
110+
}
111+
return ListBucketsForProject(project_id, std::forward<Options>(options)...);
112+
}
113+
114+
/**
115+
* Fetch the bucket metadata and return it.
85116
*
86117
* @param bucket_name query metadata information about this bucket.
87118
* @param options a list of optional query parameters and/or request headers.

google/cloud/storage/client_options.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ void ClientOptions::SetupFromEnvironment() {
7575
set_enable_raw_client_tracing(true);
7676
}
7777
}
78+
79+
char const* project_id = std::getenv("GOOGLE_CLOUD_PROJECT");
80+
if (project_id != nullptr) {
81+
project_id_ = project_id;
82+
}
7883
}
7984

8085
} // namespace STORAGE_CLIENT_NS

google/cloud/storage/client_options.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ class ClientOptions {
7171
return *this;
7272
}
7373

74+
std::string const& project_id() const { return project_id_; }
75+
ClientOptions& set_project_id(std::string v) {
76+
project_id_ = std::move(v);
77+
return *this;
78+
}
79+
7480
private:
7581
void SetupFromEnvironment();
7682

@@ -80,6 +86,7 @@ class ClientOptions {
8086
std::string version_;
8187
bool enable_http_tracing_;
8288
bool enable_raw_client_tracing_;
89+
std::string project_id_;
8390
};
8491
} // namespace STORAGE_CLIENT_NS
8592
} // namespace storage

google/cloud/storage/examples/run_examples_utils.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ run_program_examples() {
6363
#
6464
case ${example} in
6565
list-buckets)
66+
arguments=""
67+
export GOOGLE_CLOUD_PROJECT="${PROJECT_ID}"
68+
;;
69+
list-buckets-for-project)
6670
arguments="${PROJECT_ID}"
6771
;;
6872
insert-object)
@@ -150,6 +154,7 @@ run_all_bucket_examples() {
150154
# test. Currently get-metadata assumes that $bucket_name is already created.
151155
readonly BUCKET_EXAMPLES_COMMANDS=$(tr '\n' ',' <<_EOF_
152156
list-buckets
157+
list-buckets-for-project
153158
get-bucket-metadata
154159
list-objects
155160
_EOF_

google/cloud/storage/examples/storage_bucket_samples.cc

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,44 @@ void PrintUsage(int argc, char* argv[], std::string const& msg) {
4848
}
4949

5050
void ListBuckets(storage::Client client, int& argc, char* argv[]) {
51-
if (argc < 2) {
52-
throw Usage{"list-buckets <project-id>"};
51+
if (argc != 1) {
52+
throw Usage{"list-buckets"};
5353
}
54-
auto project_id = ConsumeArg(argc, argv);
5554
//! [list buckets] [START storage_list_buckets]
56-
[](google::cloud::storage::Client client, std::string project_id) {
55+
namespace gcs = google::cloud::storage;
56+
[](gcs::Client client) {
5757
int count = 0;
58-
for (auto&& meta : client.ListBuckets(project_id)) {
58+
for (gcs::BucketMetadata const& meta : client.ListBuckets()) {
5959
std::cout << meta.name() << std::endl;
6060
++count;
6161
}
6262
if (count == 0) {
63-
std::cout << "No buckets in project " << project_id << std::endl;
63+
std::cout << "No buckets in default project" << std::endl;
6464
}
6565
}
6666
//! [list buckets] [END storage_list_buckets]
67+
(std::move(client));
68+
}
69+
70+
void ListBucketsForProject(storage::Client client, int& argc, char* argv[]) {
71+
if (argc != 2) {
72+
throw Usage{"list-buckets-for-project <project-id>"};
73+
}
74+
auto project_id = ConsumeArg(argc, argv);
75+
//! [list buckets for project]
76+
namespace gcs = google::cloud::storage;
77+
[](gcs::Client client, std::string project_id) {
78+
int count = 0;
79+
for (gcs::BucketMetadata const& meta :
80+
client.ListBucketsForProject(project_id)) {
81+
std::cout << meta.name() << std::endl;
82+
++count;
83+
}
84+
if (count == 0) {
85+
std::cout << "No buckets in project " << project_id << std::endl;
86+
}
87+
}
88+
//! [list buckets for project]
6789
(std::move(client), project_id);
6890
}
6991

@@ -97,6 +119,7 @@ int main(int argc, char* argv[]) try {
97119
using CommandType = std::function<void(storage::Client, int&, char* [])>;
98120
std::map<std::string, CommandType> commands = {
99121
{"list-buckets", &ListBuckets},
122+
{"list-buckets-for-project", &ListBucketsForProject},
100123
{"get-bucket-metadata", &GetBucketMetadata},
101124
{"list-objects", &ListObjects},
102125
};

google/cloud/storage/storage_client_options_test.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,24 @@ TEST_F(ClientOptionsTest, SetCredentials) {
9393
EXPECT_FALSE(creds.get() == other.get());
9494
}
9595

96+
TEST_F(ClientOptionsTest, ProjectIdFromEnvironment) {
97+
google::cloud::internal::SetEnv("GOOGLE_CLOUD_PROJECT", "test-project-id");
98+
ClientOptions options(CreateInsecureCredentials());
99+
EXPECT_EQ("test-project-id", options.project_id());
100+
}
101+
102+
TEST_F(ClientOptionsTest, ProjectIdFromEnvironmentNotSet) {
103+
google::cloud::internal::UnsetEnv("GOOGLE_CLOUD_PROJECT");
104+
ClientOptions options(CreateInsecureCredentials());
105+
EXPECT_EQ("", options.project_id());
106+
}
107+
108+
TEST_F(ClientOptionsTest, SetProjectId) {
109+
ClientOptions options(CreateInsecureCredentials());
110+
options.set_project_id("test-project-id");
111+
EXPECT_EQ("test-project-id", options.project_id());
112+
}
113+
96114
} // namespace
97115
} // namespace STORAGE_CLIENT_NS
98116
} // namespace storage

google/cloud/storage/tests/bucket_integration_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ TEST_F(BucketIntegrationTest, BasicCRUD) {
5050
auto project_id = BucketTestEnvironment::project_id();
5151
Client client;
5252

53-
auto buckets = client.ListBuckets(project_id);
53+
auto buckets = client.ListBucketsForProject(project_id);
5454
std::vector<BucketMetadata> initial_buckets(buckets.begin(), buckets.end());
5555
// Since `bucket_name` should be available, we do not expect this list to be
5656
// empty.

0 commit comments

Comments
 (0)