From 68c38c38cc993d62782b8eb19d1f6f0f316b0676 Mon Sep 17 00:00:00 2001 From: Ilia Shakhov Date: Fri, 19 Jan 2024 08:52:13 +0000 Subject: [PATCH 1/3] Show exclusive nodes in embedded ui KIKIMR-20675 --- ydb/core/viewer/json_compute.h | 5 +++++ ydb/core/viewer/json_tenantinfo.h | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ydb/core/viewer/json_compute.h b/ydb/core/viewer/json_compute.h index ffab5483c1e1..e4d9ef243646 100644 --- a/ydb/core/viewer/json_compute.h +++ b/ydb/core/viewer/json_compute.h @@ -284,6 +284,11 @@ class TJsonCompute : public TViewerPipeClient { for (const NKikimrHive::THiveNodeStats& nodeStat : nodeStats) { auto nodeId = nodeStat.GetNodeId(); if (IsRequiredNode(nodeId)) { + const auto& nodeDomain = nodeStat.GetNodeDomain(); + TPathId subDomainKey(nodeDomain.GetSchemeShard(), nodeDomain.GetPathId()); + if (FilterSubDomain && FilterSubDomain != subDomainKey) { + continue; + } NodeIds.emplace_back(nodeId); // order is important TActorId whiteboardServiceId = MakeNodeWhiteboardServiceId(nodeId); THolder request = MakeHolder(); diff --git a/ydb/core/viewer/json_tenantinfo.h b/ydb/core/viewer/json_tenantinfo.h index 36a4a4481766..55abe40afe11 100644 --- a/ydb/core/viewer/json_tenantinfo.h +++ b/ydb/core/viewer/json_tenantinfo.h @@ -667,9 +667,11 @@ class TJsonTenantInfo : public TViewerPipeClient { if (tenant.GetType() == NKikimrViewer::Serverless) { tenant.SetStorageAllocatedSize(tenant.GetMetrics().GetStorage()); - tenant.SetMemoryUsed(tenant.GetMetrics().GetMemory()); - tenant.ClearMemoryLimit(); - tenant.SetCoresUsed(static_cast(tenant.GetMetrics().GetCPU()) / 1000000); + if (tenant.NodeIdsSize() == 0) { + tenant.SetMemoryUsed(tenant.GetMetrics().GetMemory()); + tenant.ClearMemoryLimit(); + tenant.SetCoresUsed(static_cast(tenant.GetMetrics().GetCPU()) / 1000000); + } } if (Tablets) { From d834141f4001bf6d9bac3d3f040044b3fd3a32ac Mon Sep 17 00:00:00 2001 From: Ilia Shakhov Date: Tue, 23 Jan 2024 09:24:51 +0000 Subject: [PATCH 2/3] Add exclusive nodes to new json/nodes endpoint KIKIMR-20675 --- ydb/core/viewer/json_compute.h | 4 +- ydb/core/viewer/json_nodes.h | 16 +- ydb/core/viewer/json_tenantinfo.h | 3 +- ydb/core/viewer/viewer_ut.cpp | 432 ++++++++++++++++++++++++++++++ 4 files changed, 451 insertions(+), 4 deletions(-) diff --git a/ydb/core/viewer/json_compute.h b/ydb/core/viewer/json_compute.h index e4d9ef243646..4c6f0463c902 100644 --- a/ydb/core/viewer/json_compute.h +++ b/ydb/core/viewer/json_compute.h @@ -285,8 +285,8 @@ class TJsonCompute : public TViewerPipeClient { auto nodeId = nodeStat.GetNodeId(); if (IsRequiredNode(nodeId)) { const auto& nodeDomain = nodeStat.GetNodeDomain(); - TPathId subDomainKey(nodeDomain.GetSchemeShard(), nodeDomain.GetPathId()); - if (FilterSubDomain && FilterSubDomain != subDomainKey) { + const TPathId subDomain(nodeDomain.GetSchemeShard(), nodeDomain.GetPathId()); + if (FilterSubDomain && FilterSubDomain != subDomain) { continue; } NodeIds.emplace_back(nodeId); // order is important diff --git a/ydb/core/viewer/json_nodes.h b/ydb/core/viewer/json_nodes.h index 2db9b9a124aa..f663e38a3ad4 100644 --- a/ydb/core/viewer/json_nodes.h +++ b/ydb/core/viewer/json_nodes.h @@ -40,6 +40,7 @@ class TJsonNodes : public TViewerPipeClient { TJsonSettings JsonSettings; ui32 Timeout = 0; TString FilterTenant; + TSubDomainKey FilterSubDomainKey; TString FilterPath; TString FilterStoragePool; std::unordered_set FilterNodeIds; @@ -405,6 +406,11 @@ class TJsonNodes : public TViewerPipeClient { if (HiveId == 0) { HiveId = entry.DomainInfo->Params.GetHive(); } + if (!FilterSubDomainKey) { + const auto ownerId = entry.DomainInfo->DomainKey.OwnerId; + const auto localPathId = entry.DomainInfo->DomainKey.LocalPathId; + FilterSubDomainKey = TSubDomainKey(ownerId, localPathId); + } if (entry.DomainInfo->ResourcesDomainKey && entry.DomainInfo->DomainKey != entry.DomainInfo->ResourcesDomainKey) { TPathId resourceDomainKey(entry.DomainInfo->ResourcesDomainKey); BLOG_TRACE("Requesting navigate for resource domain " << resourceDomainKey); @@ -461,6 +467,10 @@ class TJsonNodes : public TViewerPipeClient { void Handle(TEvHive::TEvResponseHiveNodeStats::TPtr& ev) { BLOG_TRACE("ResponseHiveNodeStats()"); for (const NKikimrHive::THiveNodeStats& nodeStats : ev->Get()->Record.GetNodeStats()) { + const TSubDomainKey nodeSubDomainKey = TSubDomainKey(nodeStats.GetNodeDomain()); + if (FilterSubDomainKey && FilterSubDomainKey != nodeSubDomainKey) { + continue; + } ui32 nodeId = nodeStats.GetNodeId(); auto& tabletInfo(TabletInfo[nodeId]); for (const NKikimrHive::THiveDomainStatsStateCount& stateStats : nodeStats.GetStateStats()) { @@ -514,14 +524,18 @@ class TJsonNodes : public TViewerPipeClient { } void Handle(TEvStateStorage::TEvBoardInfo::TPtr& ev) { - BLOG_TRACE("Received TEvBoardInfo"); if (ev->Get()->Status == TEvStateStorage::TEvBoardInfo::EStatus::Ok) { + BLOG_TRACE("Received TEvBoardInfo"); for (const auto& [actorId, infoEntry] : ev->Get()->InfoEntries) { auto nodeId(actorId.NodeId()); BLOG_TRACE("BoardInfo filter node by " << nodeId); FilterNodeIds.insert(nodeId); } + } else { + BLOG_TRACE("Error receiving TEvBoardInfo response"); + FilterNodeIds = { 0 }; } + if (--RequestsBeforeNodeList == 0) { ProcessNodeIds(); } diff --git a/ydb/core/viewer/json_tenantinfo.h b/ydb/core/viewer/json_tenantinfo.h index 55abe40afe11..d507ff2a8b2f 100644 --- a/ydb/core/viewer/json_tenantinfo.h +++ b/ydb/core/viewer/json_tenantinfo.h @@ -667,7 +667,8 @@ class TJsonTenantInfo : public TViewerPipeClient { if (tenant.GetType() == NKikimrViewer::Serverless) { tenant.SetStorageAllocatedSize(tenant.GetMetrics().GetStorage()); - if (tenant.NodeIdsSize() == 0) { + const bool noExclusiveNodes = tenantNodes.empty(); + if (noExclusiveNodes) { tenant.SetMemoryUsed(tenant.GetMetrics().GetMemory()); tenant.ClearMemoryLimit(); tenant.SetCoresUsed(static_cast(tenant.GetMetrics().GetCPU()) / 1000000); diff --git a/ydb/core/viewer/viewer_ut.cpp b/ydb/core/viewer/viewer_ut.cpp index 40c989d9f65a..16ed1a79d0d4 100644 --- a/ydb/core/viewer/viewer_ut.cpp +++ b/ydb/core/viewer/viewer_ut.cpp @@ -600,4 +600,436 @@ Y_UNIT_TEST_SUITE(Viewer) { StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Green, 80, 100, true); StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Green, 90, 100, true); } + + Y_UNIT_TEST(ServerlessNodesPage) + { + TPortManager tp; + ui16 port = tp.GetPort(2134); + ui16 grpcPort = tp.GetPort(2135); + auto settings = TServerSettings(port) + .SetNodeCount(1) + .SetUseRealThreads(false) + .SetDomainName("Root") + .InitKikimrRunConfig(); + TServer server(settings); + server.EnableGRpc(grpcPort); + + TClient client(settings); + TTestActorRuntime& runtime = *server.GetRuntime(); + runtime.GetAppData().DynamicNameserviceConfig->MaxStaticNodeId = 0; + + TActorId sender = runtime.AllocateEdgeActor(); + TAutoPtr handle; + + THttpRequest httpReq(HTTP_METHOD_GET); + httpReq.CgiParameters.emplace("tenant", "/Root/serverless"); + httpReq.CgiParameters.emplace("tablets", "true"); + httpReq.CgiParameters.emplace("enums", "true"); + httpReq.CgiParameters.emplace("sort", ""); + httpReq.CgiParameters.emplace("type", "any"); + auto page = MakeHolder("viewer", "title"); + TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); + auto request = MakeHolder(monReq); + + bool firstNavigateResponse = true; + auto observerFunc = [&](TAutoPtr& ev) { + switch (ev->GetTypeRewrite()) { + case TEvTxProxySchemeCache::EvNavigateKeySetResult: { + auto *x = reinterpret_cast(&ev); + TSchemeCacheNavigate::TEntry& entry((*x)->Get()->Request->ResultSet.front()); + if (firstNavigateResponse) { + firstNavigateResponse = false; + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Path = {"Root", "serverless"}; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo->DomainKey = {7000000000, 2}; + entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; + } else { + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Path = {"Root", "shared"}; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo->DomainKey = {7000000000, 1}; + entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; + entry.DomainInfo->Params.SetHive(NKikimr::Tests::Hive); + } + break; + } + case TEvHive::EvResponseHiveNodeStats: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + + auto *nodeStats = record.MutableNodeStats()->Add(); + nodeStats->SetNodeId(1); + auto *stateStats = nodeStats->MutableStateStats()->Add(); + stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); + stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); + stateStats->SetCount(1); + break; + } + case TEvWhiteboard::EvTabletStateResponse: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + + auto tablet = record.AddTabletStateInfo(); + tablet->SetTabletId(100); + tablet->SetType(NKikimrTabletBase::TTabletTypes::DataShard); + tablet->SetNodeId(1); + tablet->SetGeneration(2); + break; + } + case TEvInterconnect::EvNodesInfo: { + auto *x = reinterpret_cast(&ev); + auto &nodes = (*x)->Get()->Nodes; + nodes.clear(); + TEvInterconnect::TNodeInfo node; + node.NodeId = 1; + nodes.push_back(node); + break; + } + case TEvWhiteboard::EvSystemStateResponse: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + auto *systemStateInfo = record.AddSystemStateInfo(); + systemStateInfo->SetHost("host.yandex.net"); + break; + } + case TEvStateStorage::EvBoardInfo: { + auto *x = reinterpret_cast(&ev); + auto *record = (*x)->Get(); + using EStatus = TEvStateStorage::TEvBoardInfo::EStatus; + const_cast(record->Status) = EStatus::NotAvailable; + record->InfoEntries.clear(); + break; + } + } + + return TTestActorRuntime::EEventAction::PROCESS; + }; + runtime.SetObserverFunc(observerFunc); + + runtime.Send(new IEventHandle(NKikimr::NViewer::MakeViewerID(0), sender, request.Release(), 0)); + NMon::TEvHttpInfoRes* result = runtime.GrabEdgeEvent(handle); + + size_t pos = result->Answer.find('{'); + TString jsonResult = result->Answer.substr(pos); + Ctest << "json result: " << jsonResult << Endl; + NJson::TJsonValue json; + try { + NJson::ReadJsonTree(jsonResult, &json, true); + } + catch (yexception ex) { + Ctest << ex.what() << Endl; + } + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "0"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "0"); + } + + Y_UNIT_TEST(ServerlessWithExclusiveNodes) + { + TPortManager tp; + ui16 port = tp.GetPort(2134); + ui16 grpcPort = tp.GetPort(2135); + auto settings = TServerSettings(port) + .SetNodeCount(2) + .SetUseRealThreads(false) + .SetDomainName("Root") + .InitKikimrRunConfig(); + TServer server(settings); + server.EnableGRpc(grpcPort); + + TClient client(settings); + TTestActorRuntime& runtime = *server.GetRuntime(); + runtime.GetAppData().DynamicNameserviceConfig->MaxStaticNodeId = 0; + + TActorId sender = runtime.AllocateEdgeActor(); + TAutoPtr handle; + + THttpRequest httpReq(HTTP_METHOD_GET); + httpReq.CgiParameters.emplace("tenant", "/Root/serverless"); + httpReq.CgiParameters.emplace("tablets", "true"); + httpReq.CgiParameters.emplace("enums", "true"); + httpReq.CgiParameters.emplace("sort", ""); + httpReq.CgiParameters.emplace("type", "any"); + auto page = MakeHolder("viewer", "title"); + TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); + auto request = MakeHolder(monReq); + + bool firstNavigateResponse = true; + auto observerFunc = [&](TAutoPtr& ev) { + switch (ev->GetTypeRewrite()) { + case TEvTxProxySchemeCache::EvNavigateKeySetResult: { + auto *x = reinterpret_cast(&ev); + TSchemeCacheNavigate::TEntry& entry((*x)->Get()->Request->ResultSet.front()); + if (firstNavigateResponse) { + firstNavigateResponse = false; + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Path = {"Root", "serverless"}; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo->DomainKey = {7000000000, 2}; + entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; + } else { + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Path = {"Root", "shared"}; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo->DomainKey = {7000000000, 1}; + entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; + entry.DomainInfo->Params.SetHive(NKikimr::Tests::Hive); + } + break; + } + case TEvHive::EvResponseHiveNodeStats: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + + auto *nodeStats = record.MutableNodeStats()->Add(); + nodeStats->SetNodeId(1); + auto *stateStats = nodeStats->MutableStateStats()->Add(); + stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); + stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); + stateStats->SetCount(1); + + nodeStats = record.MutableNodeStats()->Add(); + nodeStats->SetNodeId(2); + stateStats = nodeStats->MutableStateStats()->Add(); + stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::Coordinator); + stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); + stateStats->SetCount(1); + break; + } + case TEvWhiteboard::EvTabletStateResponse: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + + if ((*x)->Cookie == 1) { + auto tablet = record.AddTabletStateInfo(); + tablet->SetType(NKikimrTabletBase::TTabletTypes::DataShard); + tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); + tablet->SetCount(1); + tablet->SetNodeId(1); + } else if ((*x)->Cookie == 2) { + auto tablet = record.AddTabletStateInfo(); + tablet->SetType(NKikimrTabletBase::TTabletTypes::Coordinator); + tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); + tablet->SetCount(1); + tablet->SetNodeId(2); + } + break; + } + case TEvInterconnect::EvNodesInfo: { + auto *x = reinterpret_cast(&ev); + auto &nodes = (*x)->Get()->Nodes; + nodes.clear(); + TEvInterconnect::TNodeInfo node; + node.NodeId = 1; + nodes.push_back(node); + TEvInterconnect::TNodeInfo exclusiveNode; + exclusiveNode.NodeId = 2; + nodes.push_back(exclusiveNode); + break; + } + case TEvWhiteboard::EvSystemStateResponse: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + if ((*x)->Cookie == 1) { + auto *systemStateInfo = record.AddSystemStateInfo(); + systemStateInfo->SetHost("host.yandex.net"); + } else if ((*x)->Cookie == 2) { + auto *systemStateInfo = record.AddSystemStateInfo(); + systemStateInfo->SetHost("exclusive.host.yandex.net"); + } + break; + } + case TEvStateStorage::EvBoardInfo: { + auto *x = reinterpret_cast(&ev); + auto *record = (*x)->Get(); + using EStatus = TEvStateStorage::TEvBoardInfo::EStatus; + const_cast(record->Status) = EStatus::Ok; + record->InfoEntries[TActorId(2, 0, 0, 0)] = {}; + break; + } + } + + return TTestActorRuntime::EEventAction::PROCESS; + }; + runtime.SetObserverFunc(observerFunc); + + runtime.Send(new IEventHandle(NKikimr::NViewer::MakeViewerID(0), sender, request.Release(), 0)); + NMon::TEvHttpInfoRes* result = runtime.GrabEdgeEvent(handle); + + size_t pos = result->Answer.find('{'); + TString jsonResult = result->Answer.substr(pos); + Ctest << "json result: " << jsonResult << Endl; + NJson::TJsonValue json; + try { + NJson::ReadJsonTree(jsonResult, &json, true); + } + catch (yexception ex) { + Ctest << ex.what() << Endl; + } + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "1"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "1"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("Nodes").GetArray().size(), 1); + auto node = json.GetMap().at("Nodes").GetArray()[0].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(node.at("NodeId"), 2); + UNIT_ASSERT_VALUES_EQUAL(node.at("SystemState").GetMap().at("Host"), "exclusive.host.yandex.net"); + UNIT_ASSERT_VALUES_EQUAL(node.at("Tablets").GetArray().size(), 1); + auto tablet = node.at("Tablets").GetArray()[0].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("Count"), 1); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("State"), "Green"); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("Type"), "Coordinator"); + } + + Y_UNIT_TEST(SharedDoesntShowExclusiveNodes) + { + TPortManager tp; + ui16 port = tp.GetPort(2134); + ui16 grpcPort = tp.GetPort(2135); + auto settings = TServerSettings(port) + .SetNodeCount(2) + .SetUseRealThreads(false) + .SetDomainName("Root") + .InitKikimrRunConfig(); + TServer server(settings); + server.EnableGRpc(grpcPort); + + TClient client(settings); + TTestActorRuntime& runtime = *server.GetRuntime(); + runtime.GetAppData().DynamicNameserviceConfig->MaxStaticNodeId = 0; + + TActorId sender = runtime.AllocateEdgeActor(); + TAutoPtr handle; + + THttpRequest httpReq(HTTP_METHOD_GET); + httpReq.CgiParameters.emplace("tenant", "Root/shared"); + httpReq.CgiParameters.emplace("tablets", "true"); + httpReq.CgiParameters.emplace("enums", "true"); + httpReq.CgiParameters.emplace("sort", ""); + httpReq.CgiParameters.emplace("type", "any"); + auto page = MakeHolder("viewer", "title"); + TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); + auto request = MakeHolder(monReq); + + auto observerFunc = [&](TAutoPtr& ev) { + switch (ev->GetTypeRewrite()) { + case TEvTxProxySchemeCache::EvNavigateKeySetResult: { + auto *x = reinterpret_cast(&ev); + TSchemeCacheNavigate::TEntry& entry((*x)->Get()->Request->ResultSet.front()); + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Path = {"Root", "shared"}; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo->DomainKey = {7000000000, 1}; + entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; + entry.DomainInfo->Params.SetHive(NKikimr::Tests::Hive); + break; + } + case TEvHive::EvResponseHiveNodeStats: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + + auto *nodeStats = record.MutableNodeStats()->Add(); + nodeStats->SetNodeId(1); + auto *stateStats = nodeStats->MutableStateStats()->Add(); + stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); + stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); + stateStats->SetCount(1); + + nodeStats = record.MutableNodeStats()->Add(); + nodeStats->SetNodeId(2); + stateStats = nodeStats->MutableStateStats()->Add(); + stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::Coordinator); + stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); + stateStats->SetCount(1); + break; + } + case TEvWhiteboard::EvTabletStateResponse: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + + if ((*x)->Cookie == 1) { + auto tablet = record.AddTabletStateInfo(); + tablet->SetType(NKikimrTabletBase::TTabletTypes::DataShard); + tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); + tablet->SetCount(1); + tablet->SetNodeId(1); + } else if ((*x)->Cookie == 2) { + auto tablet = record.AddTabletStateInfo(); + tablet->SetType(NKikimrTabletBase::TTabletTypes::Coordinator); + tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); + tablet->SetCount(1); + tablet->SetNodeId(2); + } + break; + } + case TEvInterconnect::EvNodesInfo: { + auto *x = reinterpret_cast(&ev); + auto &nodes = (*x)->Get()->Nodes; + nodes.clear(); + TEvInterconnect::TNodeInfo node; + node.NodeId = 1; + nodes.push_back(node); + TEvInterconnect::TNodeInfo exclusiveNode; + exclusiveNode.NodeId = 2; + nodes.push_back(exclusiveNode); + break; + } + case TEvWhiteboard::EvSystemStateResponse: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + record.Clear(); + if ((*x)->Cookie == 1) { + auto *systemStateInfo = record.AddSystemStateInfo(); + systemStateInfo->SetHost("host.yandex.net"); + } else if ((*x)->Cookie == 2) { + auto *systemStateInfo = record.AddSystemStateInfo(); + systemStateInfo->SetHost("exclusive.host.yandex.net"); + } + break; + } + case TEvStateStorage::EvBoardInfo: { + auto *x = reinterpret_cast(&ev); + auto *record = (*x)->Get(); + using EStatus = TEvStateStorage::TEvBoardInfo::EStatus; + const_cast(record->Status) = EStatus::Ok; + record->InfoEntries[TActorId(1, 0, 0, 0)] = {}; + break; + } + } + + return TTestActorRuntime::EEventAction::PROCESS; + }; + runtime.SetObserverFunc(observerFunc); + + runtime.Send(new IEventHandle(NKikimr::NViewer::MakeViewerID(0), sender, request.Release(), 0)); + NMon::TEvHttpInfoRes* result = runtime.GrabEdgeEvent(handle); + + size_t pos = result->Answer.find('{'); + TString jsonResult = result->Answer.substr(pos); + Ctest << "json result: " << jsonResult << Endl; + NJson::TJsonValue json; + try { + NJson::ReadJsonTree(jsonResult, &json, true); + } + catch (yexception ex) { + Ctest << ex.what() << Endl; + } + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "1"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "1"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("Nodes").GetArray().size(), 1); + auto node = json.GetMap().at("Nodes").GetArray()[0].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(node.at("NodeId"), 1); + UNIT_ASSERT_VALUES_EQUAL(node.at("SystemState").GetMap().at("Host"), "host.yandex.net"); + UNIT_ASSERT_VALUES_EQUAL(node.at("Tablets").GetArray().size(), 1); + auto tablet = node.at("Tablets").GetArray()[0].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("Count"), 1); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("State"), "Green"); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("Type"), "DataShard"); + } } From d0c301ce3b1b6c8711db4c234ea62686e42a08ca Mon Sep 17 00:00:00 2001 From: Ilia Shakhov Date: Tue, 23 Jan 2024 17:52:41 +0000 Subject: [PATCH 3/3] Fix tests KIKIMR-20675 --- ydb/core/viewer/viewer_ut.cpp | 399 ++++++++++++++-------------------- 1 file changed, 160 insertions(+), 239 deletions(-) diff --git a/ydb/core/viewer/viewer_ut.cpp b/ydb/core/viewer/viewer_ut.cpp index 16ed1a79d0d4..6fbcfba9583a 100644 --- a/ydb/core/viewer/viewer_ut.cpp +++ b/ydb/core/viewer/viewer_ut.cpp @@ -608,6 +608,7 @@ Y_UNIT_TEST_SUITE(Viewer) { ui16 grpcPort = tp.GetPort(2135); auto settings = TServerSettings(port) .SetNodeCount(1) + .SetDynamicNodeCount(1) .SetUseRealThreads(false) .SetDomainName("Root") .InitKikimrRunConfig(); @@ -616,7 +617,6 @@ Y_UNIT_TEST_SUITE(Viewer) { TClient client(settings); TTestActorRuntime& runtime = *server.GetRuntime(); - runtime.GetAppData().DynamicNameserviceConfig->MaxStaticNodeId = 0; TActorId sender = runtime.AllocateEdgeActor(); TAutoPtr handle; @@ -631,77 +631,74 @@ Y_UNIT_TEST_SUITE(Viewer) { TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); auto request = MakeHolder(monReq); - bool firstNavigateResponse = true; + runtime.Send(new IEventHandle(NKikimr::NViewer::MakeViewerID(0), sender, request.Release(), 0)); + NMon::TEvHttpInfoRes* result = runtime.GrabEdgeEvent(handle); + + size_t pos = result->Answer.find('{'); + TString jsonResult = result->Answer.substr(pos); + Ctest << "json result: " << jsonResult << Endl; + NJson::TJsonValue json; + try { + NJson::ReadJsonTree(jsonResult, &json, true); + } + catch (yexception ex) { + Ctest << ex.what() << Endl; + } + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "0"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "0"); + } + + Y_UNIT_TEST(ServerlessWithExclusiveNodes) + { + TPortManager tp; + ui16 port = tp.GetPort(2134); + ui16 grpcPort = tp.GetPort(2135); + auto settings = TServerSettings(port) + .SetNodeCount(1) + .SetDynamicNodeCount(2) + .SetUseRealThreads(false) + .SetDomainName("Root") + .InitKikimrRunConfig(); + TServer server(settings); + server.EnableGRpc(grpcPort); + + TClient client(settings); + TTestActorRuntime& runtime = *server.GetRuntime(); + + TActorId sender = runtime.AllocateEdgeActor(); + TAutoPtr handle; + + THttpRequest httpReq(HTTP_METHOD_GET); + httpReq.CgiParameters.emplace("tenant", "/Root/serverless"); + httpReq.CgiParameters.emplace("tablets", "true"); + httpReq.CgiParameters.emplace("enums", "true"); + httpReq.CgiParameters.emplace("sort", ""); + httpReq.CgiParameters.emplace("type", "any"); + auto page = MakeHolder("viewer", "title"); + TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); + auto request = MakeHolder(monReq); + + size_t staticNodeId = 0; + size_t sharedDynNodeId = 0; + size_t exclusiveDynNodeId = 0; auto observerFunc = [&](TAutoPtr& ev) { switch (ev->GetTypeRewrite()) { - case TEvTxProxySchemeCache::EvNavigateKeySetResult: { - auto *x = reinterpret_cast(&ev); - TSchemeCacheNavigate::TEntry& entry((*x)->Get()->Request->ResultSet.front()); - if (firstNavigateResponse) { - firstNavigateResponse = false; - entry.Status = TSchemeCacheNavigate::EStatus::Ok; - entry.Path = {"Root", "serverless"}; - entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; - entry.DomainInfo->DomainKey = {7000000000, 2}; - entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; - } else { - entry.Status = TSchemeCacheNavigate::EStatus::Ok; - entry.Path = {"Root", "shared"}; - entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; - entry.DomainInfo->DomainKey = {7000000000, 1}; - entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; - entry.DomainInfo->Params.SetHive(NKikimr::Tests::Hive); - } - break; - } - case TEvHive::EvResponseHiveNodeStats: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - - auto *nodeStats = record.MutableNodeStats()->Add(); - nodeStats->SetNodeId(1); - auto *stateStats = nodeStats->MutableStateStats()->Add(); - stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); - stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); - stateStats->SetCount(1); - break; - } - case TEvWhiteboard::EvTabletStateResponse: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - - auto tablet = record.AddTabletStateInfo(); - tablet->SetTabletId(100); - tablet->SetType(NKikimrTabletBase::TTabletTypes::DataShard); - tablet->SetNodeId(1); - tablet->SetGeneration(2); - break; - } case TEvInterconnect::EvNodesInfo: { auto *x = reinterpret_cast(&ev); - auto &nodes = (*x)->Get()->Nodes; - nodes.clear(); - TEvInterconnect::TNodeInfo node; - node.NodeId = 1; - nodes.push_back(node); - break; - } - case TEvWhiteboard::EvSystemStateResponse: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - auto *systemStateInfo = record.AddSystemStateInfo(); - systemStateInfo->SetHost("host.yandex.net"); + TVector &nodes = (*x)->Get()->Nodes; + UNIT_ASSERT_EQUAL(nodes.size(), 3); + staticNodeId = nodes[0]; + sharedDynNodeId = nodes[1]; + exclusiveDynNodeId = nodes[2]; break; } case TEvStateStorage::EvBoardInfo: { auto *x = reinterpret_cast(&ev); auto *record = (*x)->Get(); using EStatus = TEvStateStorage::TEvBoardInfo::EStatus; - const_cast(record->Status) = EStatus::NotAvailable; - record->InfoEntries.clear(); + const_cast(record->Status) = EStatus::Ok; + TActorId actorOnExclusiveDynNode = TActorId(exclusiveDynNodeId, 0, 0, 0); + record->InfoEntries[actorOnExclusiveDynNode] = {}; break; } } @@ -723,17 +720,21 @@ Y_UNIT_TEST_SUITE(Viewer) { catch (yexception ex) { Ctest << ex.what() << Endl; } - UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "0"); - UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "0"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "1"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "1"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("Nodes").GetArray().size(), 1); + auto node = json.GetMap().at("Nodes").GetArray()[0].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(node.at("NodeId"), exclusiveDynNodeId); } - Y_UNIT_TEST(ServerlessWithExclusiveNodes) + Y_UNIT_TEST(SharedDoesntShowExclusiveNodes) { TPortManager tp; ui16 port = tp.GetPort(2134); ui16 grpcPort = tp.GetPort(2135); auto settings = TServerSettings(port) - .SetNodeCount(2) + .SetNodeCount(1) + .SetDynamicNodeCount(2) .SetUseRealThreads(false) .SetDomainName("Root") .InitKikimrRunConfig(); @@ -742,13 +743,12 @@ Y_UNIT_TEST_SUITE(Viewer) { TClient client(settings); TTestActorRuntime& runtime = *server.GetRuntime(); - runtime.GetAppData().DynamicNameserviceConfig->MaxStaticNodeId = 0; TActorId sender = runtime.AllocateEdgeActor(); TAutoPtr handle; THttpRequest httpReq(HTTP_METHOD_GET); - httpReq.CgiParameters.emplace("tenant", "/Root/serverless"); + httpReq.CgiParameters.emplace("tenant", "Root/shared"); httpReq.CgiParameters.emplace("tablets", "true"); httpReq.CgiParameters.emplace("enums", "true"); httpReq.CgiParameters.emplace("sort", ""); @@ -757,92 +757,18 @@ Y_UNIT_TEST_SUITE(Viewer) { TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); auto request = MakeHolder(monReq); - bool firstNavigateResponse = true; + size_t staticNodeId = 0; + size_t sharedDynNodeId = 0; + size_t exclusiveDynNodeId = 0; auto observerFunc = [&](TAutoPtr& ev) { switch (ev->GetTypeRewrite()) { - case TEvTxProxySchemeCache::EvNavigateKeySetResult: { - auto *x = reinterpret_cast(&ev); - TSchemeCacheNavigate::TEntry& entry((*x)->Get()->Request->ResultSet.front()); - if (firstNavigateResponse) { - firstNavigateResponse = false; - entry.Status = TSchemeCacheNavigate::EStatus::Ok; - entry.Path = {"Root", "serverless"}; - entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; - entry.DomainInfo->DomainKey = {7000000000, 2}; - entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; - } else { - entry.Status = TSchemeCacheNavigate::EStatus::Ok; - entry.Path = {"Root", "shared"}; - entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; - entry.DomainInfo->DomainKey = {7000000000, 1}; - entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; - entry.DomainInfo->Params.SetHive(NKikimr::Tests::Hive); - } - break; - } - case TEvHive::EvResponseHiveNodeStats: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - - auto *nodeStats = record.MutableNodeStats()->Add(); - nodeStats->SetNodeId(1); - auto *stateStats = nodeStats->MutableStateStats()->Add(); - stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); - stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); - stateStats->SetCount(1); - - nodeStats = record.MutableNodeStats()->Add(); - nodeStats->SetNodeId(2); - stateStats = nodeStats->MutableStateStats()->Add(); - stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::Coordinator); - stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); - stateStats->SetCount(1); - break; - } - case TEvWhiteboard::EvTabletStateResponse: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - - if ((*x)->Cookie == 1) { - auto tablet = record.AddTabletStateInfo(); - tablet->SetType(NKikimrTabletBase::TTabletTypes::DataShard); - tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); - tablet->SetCount(1); - tablet->SetNodeId(1); - } else if ((*x)->Cookie == 2) { - auto tablet = record.AddTabletStateInfo(); - tablet->SetType(NKikimrTabletBase::TTabletTypes::Coordinator); - tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); - tablet->SetCount(1); - tablet->SetNodeId(2); - } - break; - } case TEvInterconnect::EvNodesInfo: { auto *x = reinterpret_cast(&ev); - auto &nodes = (*x)->Get()->Nodes; - nodes.clear(); - TEvInterconnect::TNodeInfo node; - node.NodeId = 1; - nodes.push_back(node); - TEvInterconnect::TNodeInfo exclusiveNode; - exclusiveNode.NodeId = 2; - nodes.push_back(exclusiveNode); - break; - } - case TEvWhiteboard::EvSystemStateResponse: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - if ((*x)->Cookie == 1) { - auto *systemStateInfo = record.AddSystemStateInfo(); - systemStateInfo->SetHost("host.yandex.net"); - } else if ((*x)->Cookie == 2) { - auto *systemStateInfo = record.AddSystemStateInfo(); - systemStateInfo->SetHost("exclusive.host.yandex.net"); - } + TVector &nodes = (*x)->Get()->Nodes; + UNIT_ASSERT_EQUAL(nodes.size(), 3); + staticNodeId = nodes[0]; + sharedDynNodeId = nodes[1]; + exclusiveDynNodeId = nodes[2]; break; } case TEvStateStorage::EvBoardInfo: { @@ -850,7 +776,8 @@ Y_UNIT_TEST_SUITE(Viewer) { auto *record = (*x)->Get(); using EStatus = TEvStateStorage::TEvBoardInfo::EStatus; const_cast(record->Status) = EStatus::Ok; - record->InfoEntries[TActorId(2, 0, 0, 0)] = {}; + TActorId actorOnSharedDynNode = TActorId(sharedDynNodeId, 0, 0, 0); + record->InfoEntries[actorOnSharedDynNode] = {}; break; } } @@ -876,22 +803,17 @@ Y_UNIT_TEST_SUITE(Viewer) { UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "1"); UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("Nodes").GetArray().size(), 1); auto node = json.GetMap().at("Nodes").GetArray()[0].GetMap(); - UNIT_ASSERT_VALUES_EQUAL(node.at("NodeId"), 2); - UNIT_ASSERT_VALUES_EQUAL(node.at("SystemState").GetMap().at("Host"), "exclusive.host.yandex.net"); - UNIT_ASSERT_VALUES_EQUAL(node.at("Tablets").GetArray().size(), 1); - auto tablet = node.at("Tablets").GetArray()[0].GetMap(); - UNIT_ASSERT_VALUES_EQUAL(tablet.at("Count"), 1); - UNIT_ASSERT_VALUES_EQUAL(tablet.at("State"), "Green"); - UNIT_ASSERT_VALUES_EQUAL(tablet.at("Type"), "Coordinator"); + UNIT_ASSERT_VALUES_EQUAL(node.at("NodeId"), sharedDynNodeId); } - Y_UNIT_TEST(SharedDoesntShowExclusiveNodes) + Y_UNIT_TEST(ServerlessWithExclusiveNodesCheckTable) { TPortManager tp; ui16 port = tp.GetPort(2134); ui16 grpcPort = tp.GetPort(2135); auto settings = TServerSettings(port) - .SetNodeCount(2) + .SetNodeCount(1) + .SetDynamicNodeCount(3) .SetUseRealThreads(false) .SetDomainName("Root") .InitKikimrRunConfig(); @@ -900,13 +822,13 @@ Y_UNIT_TEST_SUITE(Viewer) { TClient client(settings); TTestActorRuntime& runtime = *server.GetRuntime(); - runtime.GetAppData().DynamicNameserviceConfig->MaxStaticNodeId = 0; TActorId sender = runtime.AllocateEdgeActor(); TAutoPtr handle; THttpRequest httpReq(HTTP_METHOD_GET); - httpReq.CgiParameters.emplace("tenant", "Root/shared"); + httpReq.CgiParameters.emplace("tenant", "/Root/serverless"); + httpReq.CgiParameters.emplace("path", "/Root/serverless/users"); httpReq.CgiParameters.emplace("tablets", "true"); httpReq.CgiParameters.emplace("enums", "true"); httpReq.CgiParameters.emplace("sort", ""); @@ -915,82 +837,51 @@ Y_UNIT_TEST_SUITE(Viewer) { TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/nodes", nullptr); auto request = MakeHolder(monReq); + const TPathId SERVERLESS_DOMAIN_KEY = {7000000000, 2}; + const TPathId SHARED_DOMAIN_KEY = {7000000000, 1}; + const TPathId SERVERLESS_TABLE = {7000000001, 2}; + + size_t staticNodeId = 0; + size_t sharedDynNodeId = 0; + size_t exclusiveDynNodeId = 0; + size_t secondExclusiveDynNodeId = 0; auto observerFunc = [&](TAutoPtr& ev) { switch (ev->GetTypeRewrite()) { case TEvTxProxySchemeCache::EvNavigateKeySetResult: { auto *x = reinterpret_cast(&ev); TSchemeCacheNavigate::TEntry& entry((*x)->Get()->Request->ResultSet.front()); - entry.Status = TSchemeCacheNavigate::EStatus::Ok; - entry.Path = {"Root", "shared"}; - entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; - entry.DomainInfo->DomainKey = {7000000000, 1}; - entry.DomainInfo->ResourcesDomainKey = {7000000000, 1}; - entry.DomainInfo->Params.SetHive(NKikimr::Tests::Hive); - break; - } - case TEvHive::EvResponseHiveNodeStats: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - - auto *nodeStats = record.MutableNodeStats()->Add(); - nodeStats->SetNodeId(1); - auto *stateStats = nodeStats->MutableStateStats()->Add(); - stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); - stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); - stateStats->SetCount(1); - - nodeStats = record.MutableNodeStats()->Add(); - nodeStats->SetNodeId(2); - stateStats = nodeStats->MutableStateStats()->Add(); - stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::Coordinator); - stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); - stateStats->SetCount(1); - break; - } - case TEvWhiteboard::EvTabletStateResponse: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - - if ((*x)->Cookie == 1) { - auto tablet = record.AddTabletStateInfo(); - tablet->SetType(NKikimrTabletBase::TTabletTypes::DataShard); - tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); - tablet->SetCount(1); - tablet->SetNodeId(1); - } else if ((*x)->Cookie == 2) { - auto tablet = record.AddTabletStateInfo(); - tablet->SetType(NKikimrTabletBase::TTabletTypes::Coordinator); - tablet->SetState(NKikimrWhiteboard::TTabletStateInfo::Active); - tablet->SetCount(1); - tablet->SetNodeId(2); + TString path = CanonizePath(entry.Path); + if (path == "/Root/serverless" || entry.TableId.PathId == SERVERLESS_DOMAIN_KEY) { + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo = MakeIntrusive(SERVERLESS_DOMAIN_KEY, SHARED_DOMAIN_KEY); + } else if (path == "/Root/shared" || entry.TableId.PathId == SHARED_DOMAIN_KEY) { + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Kind = TSchemeCacheNavigate::EKind::KindExtSubdomain; + entry.DomainInfo = MakeIntrusive(SHARED_DOMAIN_KEY, SHARED_DOMAIN_KEY); + auto domains = runtime.GetAppData().DomainsInfo; + auto domain = domains->Domains.begin()->second; + ui64 hiveId = domains->GetHive(domain->DefaultHiveUid); + entry.DomainInfo->Params.SetHive(hiveId); + } else if (path == "/Root/serverless/users" || entry.TableId.PathId == SERVERLESS_TABLE) { + entry.Status = TSchemeCacheNavigate::EStatus::Ok; + entry.Kind = TSchemeCacheNavigate::EKind::KindTable; + entry.DomainInfo = MakeIntrusive(SERVERLESS_DOMAIN_KEY, SHARED_DOMAIN_KEY); + auto dirEntryInfo = MakeIntrusive(); + dirEntryInfo->Info.SetSchemeshardId(SERVERLESS_TABLE.OwnerId); + dirEntryInfo->Info.SetPathId(SERVERLESS_TABLE.LocalPathId); + entry.Self = dirEntryInfo; } break; } case TEvInterconnect::EvNodesInfo: { auto *x = reinterpret_cast(&ev); - auto &nodes = (*x)->Get()->Nodes; - nodes.clear(); - TEvInterconnect::TNodeInfo node; - node.NodeId = 1; - nodes.push_back(node); - TEvInterconnect::TNodeInfo exclusiveNode; - exclusiveNode.NodeId = 2; - nodes.push_back(exclusiveNode); - break; - } - case TEvWhiteboard::EvSystemStateResponse: { - auto *x = reinterpret_cast(&ev); - auto &record = (*x)->Get()->Record; - record.Clear(); - if ((*x)->Cookie == 1) { - auto *systemStateInfo = record.AddSystemStateInfo(); - systemStateInfo->SetHost("host.yandex.net"); - } else if ((*x)->Cookie == 2) { - auto *systemStateInfo = record.AddSystemStateInfo(); - systemStateInfo->SetHost("exclusive.host.yandex.net"); - } + TVector &nodes = (*x)->Get()->Nodes; + UNIT_ASSERT_EQUAL(nodes.size(), 4); + staticNodeId = nodes[0]; + sharedDynNodeId = nodes[1]; + exclusiveDynNodeId = nodes[2]; + secondExclusiveDynNodeId = nodes[3]; break; } case TEvStateStorage::EvBoardInfo: { @@ -998,7 +889,35 @@ Y_UNIT_TEST_SUITE(Viewer) { auto *record = (*x)->Get(); using EStatus = TEvStateStorage::TEvBoardInfo::EStatus; const_cast(record->Status) = EStatus::Ok; - record->InfoEntries[TActorId(1, 0, 0, 0)] = {}; + TActorId actorOnExclusiveDynNode = TActorId(exclusiveDynNodeId, 0, 0, 0); + record->InfoEntries[actorOnExclusiveDynNode] = {}; + TActorId actorOnSecondExclusiveDynNode = TActorId(secondExclusiveDynNodeId, 0, 0, 0); + record->InfoEntries[actorOnSecondExclusiveDynNode] = {}; + break; + } + case TEvHive::EvResponseHiveNodeStats: { + auto *x = reinterpret_cast(&ev); + auto &record = (*x)->Get()->Record; + auto *sharedNodeStats = record.MutableNodeStats()->Add(); + sharedNodeStats->SetNodeId(sharedDynNodeId); + sharedNodeStats->MutableNodeDomain()->SetSchemeShard(SHARED_DOMAIN_KEY.OwnerId); + sharedNodeStats->MutableNodeDomain()->SetPathId(SHARED_DOMAIN_KEY.LocalPathId); + + auto *exclusiveNodeStats = record.MutableNodeStats()->Add(); + exclusiveNodeStats->SetNodeId(exclusiveDynNodeId); + exclusiveNodeStats->MutableNodeDomain()->SetSchemeShard(SERVERLESS_DOMAIN_KEY.OwnerId); + exclusiveNodeStats->MutableNodeDomain()->SetPathId(SERVERLESS_DOMAIN_KEY.LocalPathId); + + auto *secondExclusiveNodeStats = record.MutableNodeStats()->Add(); + secondExclusiveNodeStats->SetNodeId(secondExclusiveDynNodeId); + secondExclusiveNodeStats->MutableNodeDomain()->SetSchemeShard(SERVERLESS_DOMAIN_KEY.OwnerId); + secondExclusiveNodeStats->MutableNodeDomain()->SetPathId(SERVERLESS_DOMAIN_KEY.LocalPathId); + + // filtered one datashard from /Root/serverless/users + auto *stateStats = secondExclusiveNodeStats->MutableStateStats()->Add(); + stateStats->SetTabletType(NKikimrTabletBase::TTabletTypes::DataShard); + stateStats->SetVolatileState(NKikimrHive::TABLET_VOLATILE_STATE_RUNNING); + stateStats->SetCount(1); break; } } @@ -1020,16 +939,18 @@ Y_UNIT_TEST_SUITE(Viewer) { catch (yexception ex) { Ctest << ex.what() << Endl; } - UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "1"); - UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "1"); - UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("Nodes").GetArray().size(), 1); - auto node = json.GetMap().at("Nodes").GetArray()[0].GetMap(); - UNIT_ASSERT_VALUES_EQUAL(node.at("NodeId"), 1); - UNIT_ASSERT_VALUES_EQUAL(node.at("SystemState").GetMap().at("Host"), "host.yandex.net"); - UNIT_ASSERT_VALUES_EQUAL(node.at("Tablets").GetArray().size(), 1); - auto tablet = node.at("Tablets").GetArray()[0].GetMap(); - UNIT_ASSERT_VALUES_EQUAL(tablet.at("Count"), 1); - UNIT_ASSERT_VALUES_EQUAL(tablet.at("State"), "Green"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("TotalNodes"), "2"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("FoundNodes"), "2"); + UNIT_ASSERT_VALUES_EQUAL(json.GetMap().at("Nodes").GetArray().size(), 2); + auto firstNode = json.GetMap().at("Nodes").GetArray()[0].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(firstNode.at("NodeId"), exclusiveDynNodeId); + UNIT_ASSERT(!firstNode.contains("Tablets")); + auto secondNode = json.GetMap().at("Nodes").GetArray()[1].GetMap(); + UNIT_ASSERT_VALUES_EQUAL(secondNode.at("NodeId"), secondExclusiveDynNodeId); + UNIT_ASSERT_VALUES_EQUAL(secondNode.at("Tablets").GetArray().size(), 1); + auto tablet = secondNode.at("Tablets").GetArray()[0].GetMap(); UNIT_ASSERT_VALUES_EQUAL(tablet.at("Type"), "DataShard"); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("State"), "Green"); + UNIT_ASSERT_VALUES_EQUAL(tablet.at("Count"), 1); } }