Skip to content

Commit 0596a8a

Browse files
ApiManager reads init_service_configs in server config (istio#366)
* ApiManager reads init_service_configs in server config * Added error handling case for no service config * Used underlying buffer to read config file * ApiManager reads the service config from server config * Revert "ApiManager reads the service config from server config" This reverts commit 7eae288a76bbe83525252bee63cfe7e13c4c9675.
1 parent 4b75025 commit 0596a8a

File tree

7 files changed

+246
-31
lines changed

7 files changed

+246
-31
lines changed

contrib/endpoints/include/api_manager/api_manager.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,6 @@ class ApiManager {
8787
virtual utils::Status GetStatistics(
8888
ApiManagerStatistics *statistics) const = 0;
8989

90-
// Return the initialization status
91-
// - Code::UNAVAILABLE Not initialized yet. The default value.
92-
// - Code::OK Successfully initialized
93-
// - Code::ABORTED Initialization was failed
94-
virtual utils::Status ConfigLoadingStatus() const = 0;
95-
9690
protected:
9791
ApiManager() {}
9892

contrib/endpoints/src/api_manager/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ cc_test(
195195
srcs = [
196196
"api_manager_test.cc",
197197
],
198+
data = glob(["testdata/*.json"]),
198199
linkstatic = 1,
199200
deps = [
200201
":api_manager",

contrib/endpoints/src/api_manager/api_manager_impl.cc

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@
1818
#include "contrib/endpoints/src/api_manager/check_workflow.h"
1919
#include "contrib/endpoints/src/api_manager/request_handler.h"
2020

21+
#include <fstream>
22+
#include <sstream>
23+
2124
namespace google {
2225
namespace api_manager {
2326

2427
namespace {
2528

2629
const std::string kConfigRolloutManaged("managed");
2730

28-
} // namespace unknown
31+
} // namespace anonymous
2932

3033
ApiManagerImpl::ApiManagerImpl(std::unique_ptr<ApiManagerEnvInterface> env,
3134
const std::string &service_config,
@@ -43,9 +46,49 @@ ApiManagerImpl::ApiManagerImpl(std::unique_ptr<ApiManagerEnvInterface> env,
4346
config_loading_status_ =
4447
utils::Status(Code::ABORTED, "Invalid service config");
4548
}
49+
} else if (global_context_->server_config()->init_service_configs_size() >
50+
0) {
51+
std::vector<std::pair<std::string, int>> list;
52+
for (auto item : global_context_->server_config()->init_service_configs()) {
53+
std::ifstream config_file(item.service_config_file_full_path());
54+
if (config_file.is_open()) {
55+
std::stringstream content;
56+
content << config_file.rdbuf();
57+
config_file.close();
58+
59+
std::string config_id;
60+
if (AddConfig(content.str(), false, &config_id).ok()) {
61+
list.push_back({config_id, round(item.traffic_percentage())});
62+
} else {
63+
global_context_->env()->LogError(
64+
"Unable to handle service config: " +
65+
item.service_config_file_full_path());
66+
67+
config_loading_status_ =
68+
utils::Status(Code::ABORTED, "Invalid service config");
69+
break;
70+
}
71+
} else {
72+
global_context_->env()->LogError("Unable to open service config: " +
73+
item.service_config_file_full_path());
74+
config_loading_status_ =
75+
utils::Status(Code::ABORTED, "Invalid service config");
76+
break;
77+
}
78+
}
79+
80+
if (config_loading_status_.code() == Code::UNAVAILABLE && list.size() > 0) {
81+
DeployConfigs(std::move(list));
82+
config_loading_status_ = utils::Status::OK;
83+
} else {
84+
service_context_map_.clear();
85+
config_loading_status_ =
86+
utils::Status(Code::ABORTED, "Invalid service config");
87+
}
4688
} else {
47-
config_loading_status_ =
48-
utils::Status(Code::ABORTED, "Invalid service config");
89+
std::string err_msg = "Service config was not specified";
90+
global_context_->env()->LogError(err_msg);
91+
config_loading_status_ = utils::Status(Code::ABORTED, err_msg);
4992
}
5093

5194
check_workflow_ = std::unique_ptr<CheckWorkflow>(new CheckWorkflow);
@@ -118,6 +161,10 @@ utils::Status ApiManagerImpl::Close() {
118161
global_context_->cloud_trace_aggregator()->SendAndClearTraces();
119162
}
120163

164+
if (!config_loading_status_.ok() || service_context_map_.empty()) {
165+
return utils::Status::OK;
166+
}
167+
121168
for (auto it : service_context_map_) {
122169
if (it.second->service_control()) {
123170
it.second->service_control()->Close();

contrib/endpoints/src/api_manager/api_manager_impl.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,6 @@ class ApiManagerImpl : public ApiManager {
6060
// Return ServiceContext for selected by WeightedSelector
6161
std::shared_ptr<context::ServiceContext> SelectService();
6262

63-
// Return the initialization status
64-
inline utils::Status ConfigLoadingStatus() const override {
65-
return config_loading_status_;
66-
}
67-
6863
private:
6964
// Use these configs according to the traffic percentage.
7065
void DeployConfigs(std::vector<std::pair<std::string, int>> &&list);

contrib/endpoints/src/api_manager/api_manager_test.cc

Lines changed: 147 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,69 @@ namespace api_manager {
3030

3131
namespace {
3232

33-
const char kServerConfigWithServiceNameConfigId[] = R"(
33+
const char kServerConfigWithSingleServiceConfig[] = R"(
3434
{
3535
"google_authentication_secret": "{}",
3636
"metadata_server_config": {
3737
"enabled": true,
3838
"url": "http://localhost"
3939
},
40-
"service_name": "bookstore.test.appspot.com",
41-
"config_id": "2017-05-01r0"
40+
"init_service_configs": [
41+
{
42+
"service_config_file_full_path": "contrib/endpoints/src/api_manager/testdata/bookstore_service_config_1.json",
43+
"traffic_percentage": 100
44+
}
45+
]
46+
}
47+
)";
48+
49+
const char kServerConfigWithPartialServiceConfig[] = R"(
50+
{
51+
"google_authentication_secret": "{}",
52+
"metadata_server_config": {
53+
"enabled": true,
54+
"url": "http://localhost"
55+
},
56+
"init_service_configs": [
57+
{
58+
"service_config_file_full_path": "contrib/endpoints/src/api_manager/testdata/bookstore_service_config_1.json",
59+
"traffic_percentage": 80
60+
},
61+
{
62+
"service_config_file_full_path": "contrib/endpoints/src/api_manager/testdata/bookstore_service_config_2.json",
63+
"traffic_percentage": 20
64+
}
65+
]
66+
}
67+
)";
68+
69+
const char kServerConfigWithPartialServiceConfigFailed[] = R"(
70+
{
71+
"google_authentication_secret": "{}",
72+
"metadata_server_config": {
73+
"enabled": true,
74+
"url": "http://localhost"
75+
},
76+
"init_service_configs": [
77+
{
78+
"service_config_file_full_path": "contrib/endpoints/src/api_manager/testdata/bookstore_service_config_1.json",
79+
"traffic_percentage": 80
80+
},
81+
{
82+
"service_config_file_full_path": "not_found.json",
83+
"traffic_percentage": 20
84+
}
85+
]
86+
}
87+
)";
88+
89+
const char kServerConfigWithNoServiceConfig[] = R"(
90+
{
91+
"google_authentication_secret": "{}",
92+
"metadata_server_config": {
93+
"enabled": true,
94+
"url": "http://localhost"
95+
}
4296
}
4397
)";
4498

@@ -69,17 +123,6 @@ const char kServiceConfig1[] = R"(
69123
}
70124
)";
71125

72-
const char kServiceConfig2[] = R"(
73-
{
74-
"name": "different.test.appspot.com",
75-
"title": "Bookstore",
76-
"control": {
77-
"environment": "servicecontrol.googleapis.com"
78-
},
79-
"id": "2017-05-01r0"
80-
}
81-
)";
82-
83126
const char kServiceForStatistics[] =
84127
"name: \"service-name\"\n"
85128
"control: {\n"
@@ -168,10 +211,10 @@ TEST_F(ApiManagerTest, InitializedOnApiManagerInstanceCreation) {
168211
std::shared_ptr<ApiManagerImpl> api_manager(
169212
std::dynamic_pointer_cast<ApiManagerImpl>(
170213
MakeApiManager(std::move(env), kServiceConfig1,
171-
kServerConfigWithServiceNameConfigId)));
214+
kServerConfigWithSingleServiceConfig)));
172215

173216
EXPECT_TRUE(api_manager);
174-
EXPECT_EQ("OK", api_manager->ConfigLoadingStatus().ToString());
217+
EXPECT_TRUE(api_manager->Enabled());
175218

176219
auto service = api_manager->SelectService();
177220
EXPECT_TRUE(service);
@@ -180,7 +223,6 @@ TEST_F(ApiManagerTest, InitializedOnApiManagerInstanceCreation) {
180223

181224
api_manager->Init();
182225

183-
EXPECT_EQ("OK", api_manager->ConfigLoadingStatus().ToString());
184226
EXPECT_TRUE(api_manager->Enabled());
185227
EXPECT_EQ("2017-05-01r0", api_manager->service("2017-05-01r0").id());
186228

@@ -190,6 +232,94 @@ TEST_F(ApiManagerTest, InitializedOnApiManagerInstanceCreation) {
190232
EXPECT_EQ("2017-05-01r0", service->service().id());
191233
}
192234

235+
TEST_F(ApiManagerTest, InitializedByConfigManager) {
236+
std::unique_ptr<MockApiManagerEnvironment> env(
237+
new ::testing::NiceMock<MockApiManagerEnvironment>());
238+
239+
std::shared_ptr<ApiManagerImpl> api_manager(
240+
std::dynamic_pointer_cast<ApiManagerImpl>(MakeApiManager(
241+
std::move(env), "", kServerConfigWithSingleServiceConfig)));
242+
243+
EXPECT_TRUE(api_manager);
244+
EXPECT_TRUE(api_manager->Enabled());
245+
EXPECT_EQ("bookstore.test.appspot.com", api_manager->service_name());
246+
EXPECT_EQ("2017-05-01r0", api_manager->service("2017-05-01r0").id());
247+
248+
api_manager->Init();
249+
250+
EXPECT_TRUE(api_manager->Enabled());
251+
EXPECT_EQ("2017-05-01r0", api_manager->service("2017-05-01r0").id());
252+
253+
auto service = api_manager->SelectService();
254+
EXPECT_TRUE(service);
255+
EXPECT_EQ("bookstore.test.appspot.com", service->service_name());
256+
EXPECT_EQ("2017-05-01r0", service->service().id());
257+
}
258+
259+
TEST_F(ApiManagerTest, kServerConfigWithPartialServiceConfig) {
260+
std::unique_ptr<MockApiManagerEnvironment> env(
261+
new ::testing::NiceMock<MockApiManagerEnvironment>());
262+
263+
std::shared_ptr<ApiManagerImpl> api_manager(
264+
std::dynamic_pointer_cast<ApiManagerImpl>(MakeApiManager(
265+
std::move(env), "", kServerConfigWithPartialServiceConfig)));
266+
267+
EXPECT_TRUE(api_manager);
268+
EXPECT_TRUE(api_manager->Enabled());
269+
EXPECT_EQ("bookstore.test.appspot.com", api_manager->service_name());
270+
EXPECT_EQ("2017-05-01r0", api_manager->service("2017-05-01r0").id());
271+
EXPECT_EQ("2017-05-01r1", api_manager->service("2017-05-01r1").id());
272+
273+
api_manager->Init();
274+
275+
EXPECT_TRUE(api_manager->Enabled());
276+
EXPECT_EQ("2017-05-01r0", api_manager->service("2017-05-01r0").id());
277+
EXPECT_EQ("2017-05-01r1", api_manager->service("2017-05-01r1").id());
278+
279+
std::unordered_map<std::string, int> counter = {{"2017-05-01r0", 0},
280+
{"2017-05-01r1", 0}};
281+
for (int i = 0; i < 100; i++) {
282+
auto service = api_manager->SelectService();
283+
EXPECT_TRUE(service);
284+
EXPECT_EQ("bookstore.test.appspot.com", service->service_name());
285+
counter[service->service().id()]++;
286+
}
287+
EXPECT_EQ(80, counter["2017-05-01r0"]);
288+
EXPECT_EQ(20, counter["2017-05-01r1"]);
289+
}
290+
291+
TEST_F(ApiManagerTest, kServerConfigWithInvaludServiceConfig) {
292+
std::unique_ptr<MockApiManagerEnvironment> env(
293+
new ::testing::NiceMock<MockApiManagerEnvironment>());
294+
295+
std::shared_ptr<ApiManagerImpl> api_manager(
296+
std::dynamic_pointer_cast<ApiManagerImpl>(MakeApiManager(
297+
std::move(env), "", kServerConfigWithPartialServiceConfigFailed)));
298+
299+
EXPECT_TRUE(api_manager);
300+
EXPECT_FALSE(api_manager->Enabled());
301+
302+
api_manager->Init();
303+
304+
EXPECT_FALSE(api_manager->Enabled());
305+
}
306+
307+
TEST_F(ApiManagerTest, kServerConfigServiceConfigNotSpecifed) {
308+
std::unique_ptr<MockApiManagerEnvironment> env(
309+
new ::testing::NiceMock<MockApiManagerEnvironment>());
310+
311+
std::shared_ptr<ApiManagerImpl> api_manager(
312+
std::dynamic_pointer_cast<ApiManagerImpl>(MakeApiManager(
313+
std::move(env), "", kServerConfigWithNoServiceConfig)));
314+
315+
EXPECT_TRUE(api_manager);
316+
EXPECT_FALSE(api_manager->Enabled());
317+
318+
api_manager->Init();
319+
320+
EXPECT_FALSE(api_manager->Enabled());
321+
}
322+
193323
} // namespace
194324

195325
} // namespace api_manager
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "bookstore.test.appspot.com",
3+
"title": "Bookstore",
4+
"http": {
5+
"rules": [
6+
{
7+
"selector": "EchoGetMessage",
8+
"get": "/echo"
9+
}
10+
]
11+
},
12+
"usage": {
13+
"rules": [
14+
{
15+
"selector": "EchoGetMessage",
16+
"allowUnregisteredCalls": true
17+
}
18+
]
19+
},
20+
"control": {
21+
"environment": "servicecontrol.googleapis.com"
22+
},
23+
"id": "2017-05-01r0"
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "bookstore.test.appspot.com",
3+
"title": "Bookstore",
4+
"http": {
5+
"rules": [
6+
{
7+
"selector": "EchoGetMessage",
8+
"get": "/echo"
9+
}
10+
]
11+
},
12+
"usage": {
13+
"rules": [
14+
{
15+
"selector": "EchoGetMessage",
16+
"allowUnregisteredCalls": true
17+
}
18+
]
19+
},
20+
"control": {
21+
"environment": "servicecontrol.googleapis.com"
22+
},
23+
"id": "2017-05-01r1"
24+
}

0 commit comments

Comments
 (0)