Skip to content

Commit 10f2783

Browse files
authored
Unsupported database type (DataStreams) by 403 http error (#930)
* Remove yexception and add try/catch * Fix by pr comments * Use {} init
1 parent 2e18015 commit 10f2783

File tree

3 files changed

+69
-30
lines changed

3 files changed

+69
-30
lines changed

ydb/core/fq/libs/actors/database_resolver.cpp

+42-19
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,31 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
138138

139139
LOG_T("ResponseProcessor::Handle(HttpIncomingResponse): got MDB API response: code=" << ev->Get()->Response->Status);
140140

141+
try {
142+
HandleResponse(ev, requestIter, errorMessage, result);
143+
} catch (...) {
144+
const TString msg = TStringBuilder() << "error while response processing, params "
145+
<< ((requestIter != Requests.end()) ? requestIter->second.ToDebugString() : TString{"unknown"})
146+
<< ", details: " << CurrentExceptionMessage();
147+
LOG_E("ResponseProccessor::Handle(TEvHttpIncomingResponse): " << msg);
148+
}
149+
150+
LOG_T("ResponseProcessor::Handle(HttpIncomingResponse): progress: "
151+
<< DatabaseId2Description.size() << " of " << Requests.size() << " requests are done");
152+
153+
if (HandledIds == Requests.size()) {
154+
SendResolvedEndpointsAndDie(errorMessage);
155+
}
156+
}
157+
158+
private:
159+
160+
void HandleResponse(
161+
NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr& ev,
162+
const TRequestMap::const_iterator& requestIter,
163+
TString& errorMessage,
164+
TMaybe<TDatabaseDescription>& result)
165+
{
141166
if (ev->Get()->Error.empty() && (ev->Get()->Response && ev->Get()->Response->Status == "200")) {
142167
errorMessage = HandleSuccessfulResponse(ev, requestIter, result);
143168
} else {
@@ -152,34 +177,26 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
152177
auto key = std::make_tuple(params.Id, params.DatabaseType, params.DatabaseAuth);
153178
if (errorMessage) {
154179
LOG_T("ResponseProcessor::Handle(HttpIncomingResponse): put value in cache"
155-
<< "; params: " << params.ToDebugString()
156-
<< ", error: " << errorMessage);
180+
<< "; params: " << params.ToDebugString()
181+
<< ", error: " << errorMessage);
157182
Cache.Put(key, errorMessage);
158183
} else {
159184
LOG_T("ResponseProcessor::Handle(HttpIncomingResponse): put value in cache"
160-
<< "; params: " << params.ToDebugString()
161-
<< ", result: " << result->ToDebugString());
185+
<< "; params: " << params.ToDebugString()
186+
<< ", result: " << result->ToDebugString());
162187
Cache.Put(key, result);
163188
}
164189
}
165-
166-
LOG_D("ResponseProcessor::Handle(HttpIncomingResponse): progress: "
167-
<< DatabaseId2Description.size() << " of " << Requests.size() << " requests are done");
168-
169-
if (HandledIds == Requests.size()) {
170-
SendResolvedEndpointsAndDie(errorMessage);
171-
}
172190
}
173191

174-
private:
175192
TString HandleSuccessfulResponse(
176193
NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr& ev,
177194
const TRequestMap::const_iterator& requestIter,
178195
TMaybe<TDatabaseDescription>& result
179196
) {
180197
if (requestIter == Requests.end()) {
181198
return "unknown request";
182-
}
199+
}
183200

184201
NJson::TJsonReaderConfig jsonConfig;
185202
NJson::TJsonValue databaseInfo;
@@ -224,12 +241,7 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
224241
const auto& status = ev->Get()->Response->Status;
225242

226243
if (status == "403") {
227-
const auto second = requestIter->second;
228-
auto mdbTypeStr = NYql::DatabaseTypeLowercase(second.DatabaseType);
229-
230-
return TStringBuilder() << "You have no permission to resolve database id into database endpoint. " <<
231-
"Please check that your service account has role " <<
232-
"`managed-" << mdbTypeStr << ".viewer`.";
244+
return TStringBuilder() << "You have no permission to resolve database id into database endpoint. " + DetailedPermissionsError(requestIter->second);
233245
}
234246

235247
auto errorMessage = ev->Get()->Error;
@@ -245,6 +257,17 @@ class TResponseProcessor : public TActorBootstrapped<TResponseProcessor>
245257
return errorMessage;
246258
}
247259

260+
261+
TString DetailedPermissionsError(const TResolveParams& params) const {
262+
263+
if (params.DatabaseType == EDatabaseType::ClickHouse || params.DatabaseType == EDatabaseType::PostgreSQL) {
264+
auto mdbTypeStr = NYql::DatabaseTypeLowercase(params.DatabaseType);
265+
return TStringBuilder() << "Please check that your service account has role " <<
266+
"`managed-" << mdbTypeStr << ".viewer`.";
267+
}
268+
return {};
269+
}
270+
248271
const TActorId Sender;
249272
TCache& Cache;
250273
const TRequestMap Requests;

ydb/core/fq/libs/actors/ut/database_resolver_ut.cpp

+25-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace {
1414
using namespace NKikimr;
1515
using namespace NFq;
1616

17+
TString NoPermissionStr = "You have no permission to resolve database id into database endpoint. ";
18+
1719
struct TTestBootstrap : public TTestActorRuntime {
1820
NConfig::TCheckpointCoordinatorConfig Settings;
1921
NActors::TActorId DatabaseResolver;
@@ -295,7 +297,7 @@ Y_UNIT_TEST_SUITE(TDatabaseResolverTests) {
295297
Y_UNIT_TEST(ClickHouse_PermissionDenied) {
296298
NYql::TIssues issues{
297299
NYql::TIssue(
298-
"You have no permission to resolve database id into database endpoint. Please check that your service account has role `managed-clickhouse.viewer`."
300+
TStringBuilder{} << NoPermissionStr << "Please check that your service account has role `managed-clickhouse.viewer`."
299301
)
300302
};
301303

@@ -363,7 +365,7 @@ Y_UNIT_TEST_SUITE(TDatabaseResolverTests) {
363365
Y_UNIT_TEST(PostgreSQL_PermissionDenied) {
364366
NYql::TIssues issues{
365367
NYql::TIssue(
366-
"You have no permission to resolve database id into database endpoint. Please check that your service account has role `managed-postgresql.viewer`."
368+
TStringBuilder{} << NoPermissionStr << "Please check that your service account has role `managed-postgresql.viewer`."
367369
)
368370
};
369371

@@ -389,6 +391,27 @@ Y_UNIT_TEST_SUITE(TDatabaseResolverTests) {
389391
issues
390392
);
391393
}
394+
395+
Y_UNIT_TEST(DataStreams_PermissionDenied) {
396+
NYql::TIssues issues{
397+
NYql::TIssue(
398+
NoPermissionStr
399+
)
400+
};
401+
Test(
402+
NYql::EDatabaseType::DataStreams,
403+
NYql::NConnector::NApi::EProtocol::PROTOCOL_UNSPECIFIED,
404+
"https://ydbc.ydb.cloud.yandex.net:8789/ydbc/cloud-prod/database?databaseId=etn021us5r9rhld1vgbh",
405+
"403",
406+
R"(
407+
{
408+
"message": "Permission denied"
409+
})",
410+
NYql::TDatabaseResolverResponse::TDatabaseDescription{
411+
},
412+
issues
413+
);
414+
}
392415
}
393416

394417
} // namespace NFq

ydb/library/yql/providers/common/db_id_async_resolver/db_async_resolver.h

+2-9
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,7 @@ inline NConnector::NApi::EDataSourceKind DatabaseTypeToDataSourceKind(EDatabaseT
4141
inline TString DatabaseTypeLowercase(EDatabaseType databaseType) {
4242
auto dump = ToString(databaseType);
4343
dump.to_lower();
44-
45-
switch (databaseType) {
46-
case EDatabaseType::ClickHouse:
47-
case EDatabaseType::PostgreSQL:
48-
return dump;
49-
default:
50-
ythrow yexception() << "Unsupported database type: " << ToString(databaseType);
51-
}
44+
return dump;
5245
}
5346

5447
// TODO: remove this function after /kikimr/yq/tests/control_plane_storage is moved to /ydb.
@@ -73,7 +66,7 @@ struct TDatabaseAuth {
7366
NConnector::NApi::EProtocol Protocol = NConnector::NApi::EProtocol::PROTOCOL_UNSPECIFIED;
7467

7568
bool operator==(const TDatabaseAuth& other) const {
76-
return std::tie(StructuredToken, AddBearerToToken, UseTls) == std::tie(other.StructuredToken, other.AddBearerToToken, other.UseTls);
69+
return std::tie(StructuredToken, AddBearerToToken, UseTls, Protocol) == std::tie(other.StructuredToken, other.AddBearerToToken, other.UseTls, Protocol);
7770
}
7871

7972
bool operator!=(const TDatabaseAuth& other) const {

0 commit comments

Comments
 (0)