diff options
author | fedor-miron <fedor-miron@yandex-team.com> | 2023-10-26 19:54:00 +0300 |
---|---|---|
committer | fedor-miron <fedor-miron@yandex-team.com> | 2023-10-26 20:42:45 +0300 |
commit | 9fc3c43b3476e61fe0df7d4c9906e44768bc7fa8 (patch) | |
tree | 0e6a3c86e7498aa399754153c7d6432dc8572286 | |
parent | b16aeda846e10a5c9df3b862583b2e36f2ef7c6a (diff) | |
download | ydb-9fc3c43b3476e61fe0df7d4c9906e44768bc7fa8.tar.gz |
YQL-16949: emit warning instead of exception on yt folder access denied
5 files changed, 62 insertions, 15 deletions
diff --git a/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.cpp b/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.cpp index 6ed2dcb3a7..316a880306 100644 --- a/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.cpp +++ b/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.cpp @@ -570,12 +570,16 @@ void CreateParents(const TVector<TString>& tables, NYT::IClientBasePtr tx) { } } +TIssue MakeIssueFromYtError(const NYT::TYtError& e, TStringBuf what, TPosition pos, bool shortErrors) { + TString errMsg = shortErrors || GetEnv("YQL_DETERMINISTIC_MODE") ? e.ShortDescription() : TString(what); + EYqlIssueCode rootIssueCode = IssueCodeForYtError(e); + return YqlIssue(pos, rootIssueCode, errMsg); +} + namespace { void FillResultFromOperationError(NCommon::TOperationResult& result, const NYT::TOperationFailedError& e, TPosition pos, bool shortErrors) { - TString errMsg = shortErrors || GetEnv("YQL_DETERMINISTIC_MODE") ? e.GetError().ShortDescription() : TString(e.what()); - EYqlIssueCode rootIssueCode = IssueCodeForYtError(e.GetError()); - TIssue rootIssue = YqlIssue(pos, rootIssueCode, errMsg); + TIssue rootIssue = MakeIssueFromYtError(e.GetError(), e.what(), pos, shortErrors); if (!e.GetFailedJobInfo().empty()) { TSet<TString> uniqueErrors; @@ -600,10 +604,7 @@ void FillResultFromOperationError(NCommon::TOperationResult& result, const NYT:: } void FillResultFromErrorResponse(NCommon::TOperationResult& result, const NYT::TErrorResponse& e, TPosition pos, bool shortErrors) { - TString errMsg = shortErrors || GetEnv("YQL_DETERMINISTIC_MODE") ? e.GetError().ShortDescription() : TString(e.what()); - - EYqlIssueCode rootIssueCode = IssueCodeForYtError(e.GetError()); - TIssue rootIssue = YqlIssue(pos, rootIssueCode, errMsg); + TIssue rootIssue = MakeIssueFromYtError(e.GetError(), e.what(), pos, shortErrors); result.SetStatus(TIssuesIds::DEFAULT_ERROR); result.AddIssue(rootIssue); diff --git a/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.h b/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.h index 151399ede7..7c5c3cce63 100644 --- a/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.h +++ b/ydb/library/yql/providers/yt/gateway/lib/yt_helpers.h @@ -67,4 +67,6 @@ IYtGateway::TCanonizedPath CanonizedPath(const TString& path); void EnsureSpecDoesntUseNativeYtTypes(const NYT::TNode& spec, TStringBuf tableName, bool read); +TIssue MakeIssueFromYtError(const NYT::TYtError& e, TStringBuf what, TPosition pos = {}, bool shortErrors = false); + } // NYql diff --git a/ydb/library/yql/providers/yt/gateway/native/ut/yql_yt_native_folders_ut.cpp b/ydb/library/yql/providers/yt/gateway/native/ut/yql_yt_native_folders_ut.cpp index 3d2a54f58b..9b2a0716e6 100644 --- a/ydb/library/yql/providers/yt/gateway/native/ut/yql_yt_native_folders_ut.cpp +++ b/ydb/library/yql/providers/yt/gateway/native/ut/yql_yt_native_folders_ut.cpp @@ -37,6 +37,12 @@ constexpr auto CYPRES_NODE_A_CONTENT = R"( "broken" = %true; "type" = "link"; > "link_broken"; + < + "user_attributes" = {}; + "target_path" = "//link_access_denied"; + "broken" = %false; + "type" = "link"; + > "link_access_denied"; ]; }; ] @@ -51,10 +57,23 @@ constexpr auto CYPRES_LINK_DEST = R"( }; ] )"; + +constexpr auto CYPRES_ACCESS_ERROR = R"( +[ + { + "error" = { + "code" = 901; + "message" = "Access denied"; + } + } +] +)"; + TVector<IYtGateway::TFolderResult::TFolderItem> EXPECTED_ITEMS { {"test/a/a", "table", R"({"user_attributes"={}})"}, {"test/a/b", "table", R"({"user_attributes"={}})"}, - {"test/a/link", "table", R"({"user_attributes"={}})"} + {"test/a/link", "table", R"({"user_attributes"={}})"}, + {"test/a/link_access_denied", "unknown", "{}"} }; TGatewaysConfig MakeGatewaysConfig(size_t port) @@ -99,6 +118,10 @@ public: private: void CheckReqAttributes(TStringBuf path, const NYT::TNode& attributes) { + if (!requiredAttributes.contains(path)) { + return; + } + THashSet<TString> attributesSet; for (const auto& attribute : attributes.AsList()) { attributesSet.insert(attribute.AsString()); @@ -125,6 +148,10 @@ private: resp.SetContent(CYPRES_LINK_DEST); return resp; } + if (path == "//link_access_denied") { + resp.SetContent(CYPRES_ACCESS_ERROR); + return resp; + } return THttpResponse{HTTP_NOT_FOUND}; } @@ -187,10 +214,14 @@ Y_UNIT_TEST(GetFolder) { folderFuture.Wait(); ytState->Gateway->CloseSession({ytState->SessionId}); auto folderRes = folderFuture.GetValue(); + UNIT_ASSERT_EQUAL_C(folderRes.Success(), true, folderRes.Issues().ToString()); UNIT_ASSERT_EQUAL( folderRes.ItemsOrFileLink, (std::variant<TVector<IYtGateway::TFolderResult::TFolderItem>, TFileLinkPtr>(EXPECTED_ITEMS))); + + UNIT_ASSERT_EQUAL(folderRes.Issues().Size(), 1); + UNIT_ASSERT_EQUAL(folderRes.Issues().back().Severity, TSeverityIds::S_WARNING); } } diff --git a/ydb/library/yql/providers/yt/gateway/native/yql_yt_native.cpp b/ydb/library/yql/providers/yt/gateway/native/yql_yt_native.cpp index 26b770adbe..2247d7b753 100644 --- a/ydb/library/yql/providers/yt/gateway/native/yql_yt_native.cpp +++ b/ydb/library/yql/providers/yt/gateway/native/yql_yt_native.cpp @@ -523,8 +523,9 @@ public: auto resolveRes = f.GetValue(); TFolderResult res; + res.AddIssues(resolveRes.Issues()); + if (!resolveRes.Success()) { - res.AddIssues(resolveRes.Issues()); res.SetStatus(resolveRes.Status()); return res; } diff --git a/ydb/library/yql/providers/yt/gateway/native/yql_yt_native_folders.cpp b/ydb/library/yql/providers/yt/gateway/native/yql_yt_native_folders.cpp index 1fdc86f8ef..84b83d6fdd 100644 --- a/ydb/library/yql/providers/yt/gateway/native/yql_yt_native_folders.cpp +++ b/ydb/library/yql/providers/yt/gateway/native/yql_yt_native_folders.cpp @@ -116,11 +116,12 @@ TFileLinkPtr SaveItemsToTempFile(const TExecContext<IYtGateway::TBatchFolderOpti IYtGateway::TBatchFolderResult ExecResolveLinks(const TExecContext<IYtGateway::TResolveOptions>::TPtr& execCtx) { try { auto batchGet = execCtx->GetEntry()->Tx->CreateBatchRequest(); - TVector<TFuture<IYtGateway::TBatchFolderResult::TFolderItem>> batchRes; + using TFolderItemWithWarning = std::pair<IYtGateway::TBatchFolderResult::TFolderItem, TMaybe<TIssue>>; + TVector<TFuture<TFolderItemWithWarning>> batchRes; for (const auto& [item, reqAttributes]: execCtx->Options_.Items()) { if (item.Type != "link") { - batchRes.push_back(MakeFuture<IYtGateway::TBatchFolderResult::TFolderItem>(std::move(item))); + batchRes.push_back(MakeFuture<TFolderItemWithWarning>({std::move(item), {}})); continue; } if (item.Attributes["broken"].AsBool()) { @@ -132,9 +133,16 @@ IYtGateway::TBatchFolderResult ExecResolveLinks(const TExecContext<IYtGateway::T batchRes.push_back( batchGet->Get(targetPath, TGetOptions().AttributeFilter(attrFilter)) - .Apply([path] (const auto& f) { - const auto linkNode = f.GetValue(); - return MakeFolderItem(linkNode, path); + .Apply([path, pos = execCtx->Options_.Pos()] (const auto& f) ->TFolderItemWithWarning { + try { + const auto linkNode = f.GetValue(); + return {MakeFolderItem(linkNode, path), {}}; + } catch (const NYT::TErrorResponse& e) { + auto warn = MakeIssueFromYtError(e.GetError(), e.what(), pos); + warn.Severity = TSeverityIds::S_WARNING; + + return {MakeFolderItem(NYT::TNode::CreateMap(), path), MakeMaybe(warn)}; + } }) ); } @@ -148,7 +156,11 @@ IYtGateway::TBatchFolderResult ExecResolveLinks(const TExecContext<IYtGateway::T batchGet->ExecuteBatch(); WaitAll(batchRes).Wait(); for (auto& f : batchRes) { - res.Items.emplace_back(f.ExtractValue()); + auto [item, maybeWarn] = f.ExtractValue(); + if (maybeWarn) { + res.AddIssue(maybeWarn.GetRef()); + } + res.Items.push_back(std::move(item)); } return res; } |