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/bigtable/instance_admin.h"
16 #include "google/cloud/bigtable/testing/table_integration_test.h"
17 #include "google/cloud/internal/getenv.h"
18 #include "google/cloud/testing_util/assert_ok.h"
19 #include "google/cloud/testing_util/chrono_literals.h"
20 #include <gmock/gmock.h>
21
22 namespace google {
23 namespace cloud {
24 namespace bigtable {
25 inline namespace BIGTABLE_CLIENT_NS {
26 namespace {
27
28 using ::testing::Contains;
29 using ::testing::Not;
30 namespace btadmin = google::bigtable::admin::v2;
31 namespace bigtable = google::cloud::bigtable;
32
33 class AdminIAMPolicyIntegrationTest
34 : public bigtable::testing::TableIntegrationTest {
35 protected:
36 std::shared_ptr<AdminClient> admin_client_;
37 std::unique_ptr<TableAdmin> table_admin_;
38 std::string service_account_;
39
SetUp()40 void SetUp() override {
41 service_account_ = google::cloud::internal::GetEnv(
42 "GOOGLE_CLOUD_CPP_BIGTABLE_TEST_SERVICE_ACCOUNT")
43 .value_or("");
44 ASSERT_FALSE(service_account_.empty());
45
46 TableIntegrationTest::SetUp();
47 admin_client_ = CreateDefaultAdminClient(
48 testing::TableTestEnvironment::project_id(), ClientOptions());
49 table_admin_ = absl::make_unique<TableAdmin>(
50 admin_client_, bigtable::testing::TableTestEnvironment::instance_id());
51 }
52 };
53
TEST_F(AdminIAMPolicyIntegrationTest,AsyncSetGetTestIamAPIsTest)54 TEST_F(AdminIAMPolicyIntegrationTest, AsyncSetGetTestIamAPIsTest) {
55 std::string const table_id = RandomTableId();
56
57 auto iam_policy = bigtable::IamPolicy({bigtable::IamBinding(
58 "roles/bigtable.reader", {"serviceAccount:" + service_account_})});
59
60 TableConfig table_config({{"fam", GcRule::MaxNumVersions(5)},
61 {"foo", GcRule::MaxAge(std::chrono::hours(24))}},
62 {"a1000", "a2000", "b3000", "m5000"});
63
64 CompletionQueue cq;
65 std::thread pool([&cq] { cq.Run(); });
66
67 future<void> chain =
68 table_admin_->AsyncListTables(cq, btadmin::Table::NAME_ONLY)
69 .then([&](future<StatusOr<std::vector<btadmin::Table>>> fut) {
70 StatusOr<std::vector<btadmin::Table>> result = fut.get();
71 EXPECT_STATUS_OK(result);
72 EXPECT_THAT(TableNames(*result),
73 Not(Contains(table_admin_->instance_name() +
74 "/tables/" + table_id)))
75 << "Table (" << table_id << ") already exists."
76 << " This is unexpected, as the table ids are"
77 << " generated at random.";
78 return table_admin_->AsyncCreateTable(cq, table_id, table_config);
79 })
80 .then([&](future<StatusOr<btadmin::Table>> fut) {
81 StatusOr<btadmin::Table> result = fut.get();
82 EXPECT_STATUS_OK(result);
83 EXPECT_THAT(result->name(), ::testing::HasSubstr(table_id));
84 return table_admin_->AsyncSetIamPolicy(cq, table_id, iam_policy);
85 })
86 .then([&](future<StatusOr<google::iam::v1::Policy>> fut) {
87 StatusOr<google::iam::v1::Policy> get_result = fut.get();
88 EXPECT_STATUS_OK(get_result);
89 return table_admin_->AsyncGetIamPolicy(cq, table_id);
90 })
91 .then([&](future<StatusOr<google::iam::v1::Policy>> fut) {
92 StatusOr<google::iam::v1::Policy> get_result = fut.get();
93 EXPECT_STATUS_OK(get_result);
94 return table_admin_->AsyncTestIamPermissions(
95 cq, table_id,
96 {"bigtable.tables.get", "bigtable.tables.readRows"});
97 })
98 .then([&](future<StatusOr<std::vector<std::string>>> fut) {
99 StatusOr<std::vector<std::string>> get_result = fut.get();
100 EXPECT_STATUS_OK(get_result);
101 EXPECT_EQ(2, get_result->size());
102 return table_admin_->AsyncDeleteTable(cq, table_id);
103 })
104 .then([&](future<Status> fut) {
105 Status delete_result = fut.get();
106 EXPECT_STATUS_OK(delete_result);
107 return table_admin_->AsyncListTables(cq, btadmin::Table::NAME_ONLY);
108 })
109 .then([&](future<StatusOr<std::vector<btadmin::Table>>> fut) {
110 StatusOr<std::vector<btadmin::Table>> result = fut.get();
111 EXPECT_STATUS_OK(result);
112 EXPECT_THAT(TableNames(*result),
113 Not(Contains(table_admin_->instance_name() +
114 "/tables/" + table_id)))
115 << "Table (" << table_id << ") already exists."
116 << " This is unexpected, as the table ids are"
117 << " generated at random.";
118 });
119
120 chain.get();
121 SUCCEED(); // we expect that previous operations do not fail.
122
123 cq.Shutdown();
124 pool.join();
125 }
126
127 /// @test Verify that IAM Policy APIs work as expected.
TEST_F(AdminIAMPolicyIntegrationTest,SetGetTestIamAPIsTest)128 TEST_F(AdminIAMPolicyIntegrationTest, SetGetTestIamAPIsTest) {
129 using GC = bigtable::GcRule;
130 std::string const table_id = RandomTableId();
131
132 // verify new table id in current table list
133 auto previous_table_list =
134 table_admin_->ListTables(btadmin::Table::NAME_ONLY);
135 ASSERT_STATUS_OK(previous_table_list);
136 ASSERT_THAT(
137 TableNames(*previous_table_list),
138 Not(Contains(table_admin_->instance_name() + "/tables/" + table_id)))
139 << "Table (" << table_id << ") already exists."
140 << " This is unexpected, as the table ids are generated at random.";
141
142 // create table config
143 bigtable::TableConfig table_config(
144 {{"fam", GC::MaxNumVersions(5)},
145 {"foo", GC::MaxAge(std::chrono::hours(24))}},
146 {"a1000", "a2000", "b3000", "m5000"});
147
148 // create table
149 ASSERT_STATUS_OK(table_admin_->CreateTable(table_id, table_config));
150
151 auto iam_policy = bigtable::IamPolicy({bigtable::IamBinding(
152 "roles/bigtable.reader", {"serviceAccount:" + service_account_})});
153
154 auto initial_policy = table_admin_->SetIamPolicy(table_id, iam_policy);
155 ASSERT_STATUS_OK(initial_policy);
156
157 auto fetched_policy = table_admin_->GetIamPolicy(table_id);
158 ASSERT_STATUS_OK(fetched_policy);
159
160 EXPECT_EQ(initial_policy->version(), fetched_policy->version());
161 EXPECT_EQ(initial_policy->etag(), fetched_policy->etag());
162
163 auto permission_set = table_admin_->TestIamPermissions(
164 table_id, {"bigtable.tables.get", "bigtable.tables.readRows"});
165 ASSERT_STATUS_OK(permission_set);
166
167 EXPECT_EQ(2, permission_set->size());
168 EXPECT_STATUS_OK(table_admin_->DeleteTable(table_id));
169 }
170
171 } // namespace
172 } // namespace BIGTABLE_CLIENT_NS
173 } // namespace bigtable
174 } // namespace cloud
175 } // namespace google
176
main(int argc,char * argv[])177 int main(int argc, char* argv[]) {
178 ::testing::InitGoogleMock(&argc, argv);
179 (void)::testing::AddGlobalTestEnvironment(
180 new google::cloud::bigtable::testing::TableTestEnvironment);
181 return RUN_ALL_TESTS();
182 }
183