Teleterm: add support for rendering status panel (#54621)

* Teleterm: define target health fields for db_servers

* Teleterm: add target health field to unified resource db resource

* Add ListDatabaseServers handler

* Enable rendering status panel on click

* Address CRs
This commit is contained in:
Lisa Kim
2025-05-14 23:18:20 +00:00
committed by GitHub
parent 0aa41337b3
commit eb9999ed06
25 changed files with 1804 additions and 399 deletions
@@ -38,7 +38,7 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Database describes a database
// Database describes a database (resource kind "db")
type Database struct {
state protoimpl.MessageState `protogen:"open.v1"`
// uri is the cluster resource URI
@@ -56,7 +56,9 @@ type Database struct {
// addr is this database ip address
Addr string `protobuf:"bytes,7,opt,name=addr,proto3" json:"addr,omitempty"`
// labels is a list of labels for this database
Labels []*Label `protobuf:"bytes,8,rep,name=labels,proto3" json:"labels,omitempty"`
Labels []*Label `protobuf:"bytes,8,rep,name=labels,proto3" json:"labels,omitempty"`
// target_health of the "db_server" that is serving this database.
TargetHealth *TargetHealth `protobuf:"bytes,9,opt,name=target_health,json=targetHealth,proto3" json:"target_health,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -147,11 +149,89 @@ func (x *Database) GetLabels() []*Label {
return nil
}
func (x *Database) GetTargetHealth() *TargetHealth {
if x != nil {
return x.TargetHealth
}
return nil
}
// DatabaseServer (db_server) describes a database heartbeat signal
// reported from an agent (db_service) that is proxying
// the database.
type DatabaseServer struct {
state protoimpl.MessageState `protogen:"open.v1"`
Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"`
Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3" json:"hostname,omitempty"`
HostId string `protobuf:"bytes,3,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"`
TargetHealth *TargetHealth `protobuf:"bytes,4,opt,name=target_health,json=targetHealth,proto3" json:"target_health,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DatabaseServer) Reset() {
*x = DatabaseServer{}
mi := &file_teleport_lib_teleterm_v1_database_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DatabaseServer) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DatabaseServer) ProtoMessage() {}
func (x *DatabaseServer) ProtoReflect() protoreflect.Message {
mi := &file_teleport_lib_teleterm_v1_database_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DatabaseServer.ProtoReflect.Descriptor instead.
func (*DatabaseServer) Descriptor() ([]byte, []int) {
return file_teleport_lib_teleterm_v1_database_proto_rawDescGZIP(), []int{1}
}
func (x *DatabaseServer) GetUri() string {
if x != nil {
return x.Uri
}
return ""
}
func (x *DatabaseServer) GetHostname() string {
if x != nil {
return x.Hostname
}
return ""
}
func (x *DatabaseServer) GetHostId() string {
if x != nil {
return x.HostId
}
return ""
}
func (x *DatabaseServer) GetTargetHealth() *TargetHealth {
if x != nil {
return x.TargetHealth
}
return nil
}
var File_teleport_lib_teleterm_v1_database_proto protoreflect.FileDescriptor
const file_teleport_lib_teleterm_v1_database_proto_rawDesc = "" +
"\n" +
"'teleport/lib/teleterm/v1/database.proto\x12\x18teleport.lib.teleterm.v1\x1a$teleport/lib/teleterm/v1/label.proto\"\xdd\x01\n" +
"'teleport/lib/teleterm/v1/database.proto\x12\x18teleport.lib.teleterm.v1\x1a$teleport/lib/teleterm/v1/label.proto\x1a,teleport/lib/teleterm/v1/target_health.proto\"\xaa\x02\n" +
"\bDatabase\x12\x10\n" +
"\x03uri\x18\x01 \x01(\tR\x03uri\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" +
@@ -160,7 +240,13 @@ const file_teleport_lib_teleterm_v1_database_proto_rawDesc = "" +
"\x04type\x18\x05 \x01(\tR\x04type\x12\x1a\n" +
"\bhostname\x18\x06 \x01(\tR\bhostname\x12\x12\n" +
"\x04addr\x18\a \x01(\tR\x04addr\x127\n" +
"\x06labels\x18\b \x03(\v2\x1f.teleport.lib.teleterm.v1.LabelR\x06labelsBTZRgithub.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1;teletermv1b\x06proto3"
"\x06labels\x18\b \x03(\v2\x1f.teleport.lib.teleterm.v1.LabelR\x06labels\x12K\n" +
"\rtarget_health\x18\t \x01(\v2&.teleport.lib.teleterm.v1.TargetHealthR\ftargetHealth\"\xa4\x01\n" +
"\x0eDatabaseServer\x12\x10\n" +
"\x03uri\x18\x01 \x01(\tR\x03uri\x12\x1a\n" +
"\bhostname\x18\x02 \x01(\tR\bhostname\x12\x17\n" +
"\ahost_id\x18\x03 \x01(\tR\x06hostId\x12K\n" +
"\rtarget_health\x18\x04 \x01(\v2&.teleport.lib.teleterm.v1.TargetHealthR\ftargetHealthBTZRgithub.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1;teletermv1b\x06proto3"
var (
file_teleport_lib_teleterm_v1_database_proto_rawDescOnce sync.Once
@@ -174,18 +260,22 @@ func file_teleport_lib_teleterm_v1_database_proto_rawDescGZIP() []byte {
return file_teleport_lib_teleterm_v1_database_proto_rawDescData
}
var file_teleport_lib_teleterm_v1_database_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_teleport_lib_teleterm_v1_database_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_teleport_lib_teleterm_v1_database_proto_goTypes = []any{
(*Database)(nil), // 0: teleport.lib.teleterm.v1.Database
(*Label)(nil), // 1: teleport.lib.teleterm.v1.Label
(*Database)(nil), // 0: teleport.lib.teleterm.v1.Database
(*DatabaseServer)(nil), // 1: teleport.lib.teleterm.v1.DatabaseServer
(*Label)(nil), // 2: teleport.lib.teleterm.v1.Label
(*TargetHealth)(nil), // 3: teleport.lib.teleterm.v1.TargetHealth
}
var file_teleport_lib_teleterm_v1_database_proto_depIdxs = []int32{
1, // 0: teleport.lib.teleterm.v1.Database.labels:type_name -> teleport.lib.teleterm.v1.Label
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
2, // 0: teleport.lib.teleterm.v1.Database.labels:type_name -> teleport.lib.teleterm.v1.Label
3, // 1: teleport.lib.teleterm.v1.Database.target_health:type_name -> teleport.lib.teleterm.v1.TargetHealth
3, // 2: teleport.lib.teleterm.v1.DatabaseServer.target_health:type_name -> teleport.lib.teleterm.v1.TargetHealth
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_teleport_lib_teleterm_v1_database_proto_init() }
@@ -194,13 +284,14 @@ func file_teleport_lib_teleterm_v1_database_proto_init() {
return
}
file_teleport_lib_teleterm_v1_label_proto_init()
file_teleport_lib_teleterm_v1_target_health_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_teleport_lib_teleterm_v1_database_proto_rawDesc), len(file_teleport_lib_teleterm_v1_database_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
File diff suppressed because it is too large Load Diff
@@ -41,6 +41,7 @@ const (
TerminalService_ListLeafClusters_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/ListLeafClusters"
TerminalService_StartHeadlessWatcher_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/StartHeadlessWatcher"
TerminalService_ListDatabaseUsers_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/ListDatabaseUsers"
TerminalService_ListDatabaseServers_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/ListDatabaseServers"
TerminalService_GetServers_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/GetServers"
TerminalService_GetAccessRequests_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/GetAccessRequests"
TerminalService_GetAccessRequest_FullMethodName = "/teleport.lib.teleterm.v1.TerminalService/GetAccessRequest"
@@ -108,6 +109,8 @@ type TerminalServiceClient interface {
StartHeadlessWatcher(ctx context.Context, in *StartHeadlessWatcherRequest, opts ...grpc.CallOption) (*StartHeadlessWatcherResponse, error)
// ListDatabaseUsers lists allowed users for the given database based on the role set.
ListDatabaseUsers(ctx context.Context, in *ListDatabaseUsersRequest, opts ...grpc.CallOption) (*ListDatabaseUsersResponse, error)
// ListDatabaseServers lists allowed users for the given database based on the role set.
ListDatabaseServers(ctx context.Context, in *ListDatabaseServersRequest, opts ...grpc.CallOption) (*ListDatabaseServersResponse, error)
// Deprecated: Do not use.
// GetServers returns filtered, sorted, and paginated servers
//
@@ -280,6 +283,16 @@ func (c *terminalServiceClient) ListDatabaseUsers(ctx context.Context, in *ListD
return out, nil
}
func (c *terminalServiceClient) ListDatabaseServers(ctx context.Context, in *ListDatabaseServersRequest, opts ...grpc.CallOption) (*ListDatabaseServersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListDatabaseServersResponse)
err := c.cc.Invoke(ctx, TerminalService_ListDatabaseServers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// Deprecated: Do not use.
func (c *terminalServiceClient) GetServers(ctx context.Context, in *GetServersRequest, opts ...grpc.CallOption) (*GetServersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
@@ -694,6 +707,8 @@ type TerminalServiceServer interface {
StartHeadlessWatcher(context.Context, *StartHeadlessWatcherRequest) (*StartHeadlessWatcherResponse, error)
// ListDatabaseUsers lists allowed users for the given database based on the role set.
ListDatabaseUsers(context.Context, *ListDatabaseUsersRequest) (*ListDatabaseUsersResponse, error)
// ListDatabaseServers lists allowed users for the given database based on the role set.
ListDatabaseServers(context.Context, *ListDatabaseServersRequest) (*ListDatabaseServersResponse, error)
// Deprecated: Do not use.
// GetServers returns filtered, sorted, and paginated servers
//
@@ -831,6 +846,9 @@ func (UnimplementedTerminalServiceServer) StartHeadlessWatcher(context.Context,
func (UnimplementedTerminalServiceServer) ListDatabaseUsers(context.Context, *ListDatabaseUsersRequest) (*ListDatabaseUsersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListDatabaseUsers not implemented")
}
func (UnimplementedTerminalServiceServer) ListDatabaseServers(context.Context, *ListDatabaseServersRequest) (*ListDatabaseServersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListDatabaseServers not implemented")
}
func (UnimplementedTerminalServiceServer) GetServers(context.Context, *GetServersRequest) (*GetServersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetServers not implemented")
}
@@ -1053,6 +1071,24 @@ func _TerminalService_ListDatabaseUsers_Handler(srv interface{}, ctx context.Con
return interceptor(ctx, in, info, handler)
}
func _TerminalService_ListDatabaseServers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListDatabaseServersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TerminalServiceServer).ListDatabaseServers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TerminalService_ListDatabaseServers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TerminalServiceServer).ListDatabaseServers(ctx, req.(*ListDatabaseServersRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TerminalService_GetServers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetServersRequest)
if err := dec(in); err != nil {
@@ -1717,6 +1753,10 @@ var TerminalService_ServiceDesc = grpc.ServiceDesc{
MethodName: "ListDatabaseUsers",
Handler: _TerminalService_ListDatabaseUsers_Handler,
},
{
MethodName: "ListDatabaseServers",
Handler: _TerminalService_ListDatabaseServers_Handler,
},
{
MethodName: "GetServers",
Handler: _TerminalService_GetServers_Handler,
@@ -0,0 +1,153 @@
//
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc (unknown)
// source: teleport/lib/teleterm/v1/target_health.proto
package teletermv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// TargetHealth describes the health status of network connectivity between
// an agent and a resource.
type TargetHealth struct {
state protoimpl.MessageState `protogen:"open.v1"`
// status is the health status, one of "", "unknown", "healthy", "unhealthy".
Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
// error is the health check error observed, when
// "status" field != "healthy".
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TargetHealth) Reset() {
*x = TargetHealth{}
mi := &file_teleport_lib_teleterm_v1_target_health_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TargetHealth) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TargetHealth) ProtoMessage() {}
func (x *TargetHealth) ProtoReflect() protoreflect.Message {
mi := &file_teleport_lib_teleterm_v1_target_health_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TargetHealth.ProtoReflect.Descriptor instead.
func (*TargetHealth) Descriptor() ([]byte, []int) {
return file_teleport_lib_teleterm_v1_target_health_proto_rawDescGZIP(), []int{0}
}
func (x *TargetHealth) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
func (x *TargetHealth) GetError() string {
if x != nil {
return x.Error
}
return ""
}
var File_teleport_lib_teleterm_v1_target_health_proto protoreflect.FileDescriptor
const file_teleport_lib_teleterm_v1_target_health_proto_rawDesc = "" +
"\n" +
",teleport/lib/teleterm/v1/target_health.proto\x12\x18teleport.lib.teleterm.v1\"<\n" +
"\fTargetHealth\x12\x16\n" +
"\x06status\x18\x01 \x01(\tR\x06status\x12\x14\n" +
"\x05error\x18\x02 \x01(\tR\x05errorBTZRgithub.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1;teletermv1b\x06proto3"
var (
file_teleport_lib_teleterm_v1_target_health_proto_rawDescOnce sync.Once
file_teleport_lib_teleterm_v1_target_health_proto_rawDescData []byte
)
func file_teleport_lib_teleterm_v1_target_health_proto_rawDescGZIP() []byte {
file_teleport_lib_teleterm_v1_target_health_proto_rawDescOnce.Do(func() {
file_teleport_lib_teleterm_v1_target_health_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_teleport_lib_teleterm_v1_target_health_proto_rawDesc), len(file_teleport_lib_teleterm_v1_target_health_proto_rawDesc)))
})
return file_teleport_lib_teleterm_v1_target_health_proto_rawDescData
}
var file_teleport_lib_teleterm_v1_target_health_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_teleport_lib_teleterm_v1_target_health_proto_goTypes = []any{
(*TargetHealth)(nil), // 0: teleport.lib.teleterm.v1.TargetHealth
}
var file_teleport_lib_teleterm_v1_target_health_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_teleport_lib_teleterm_v1_target_health_proto_init() }
func file_teleport_lib_teleterm_v1_target_health_proto_init() {
if File_teleport_lib_teleterm_v1_target_health_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_teleport_lib_teleterm_v1_target_health_proto_rawDesc), len(file_teleport_lib_teleterm_v1_target_health_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_teleport_lib_teleterm_v1_target_health_proto_goTypes,
DependencyIndexes: file_teleport_lib_teleterm_v1_target_health_proto_depIdxs,
MessageInfos: file_teleport_lib_teleterm_v1_target_health_proto_msgTypes,
}.Build()
File_teleport_lib_teleterm_v1_target_health_proto = out.File
file_teleport_lib_teleterm_v1_target_health_proto_goTypes = nil
file_teleport_lib_teleterm_v1_target_health_proto_depIdxs = nil
}
+111 -2
View File
@@ -30,9 +30,10 @@ import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
import { TargetHealth } from "./target_health_pb";
import { Label } from "./label_pb";
/**
* Database describes a database
* Database describes a database (resource kind "db")
*
* @generated from protobuf message teleport.lib.teleterm.v1.Database
*/
@@ -85,6 +86,37 @@ export interface Database {
* @generated from protobuf field: repeated teleport.lib.teleterm.v1.Label labels = 8;
*/
labels: Label[];
/**
* target_health of the "db_server" that is serving this database.
*
* @generated from protobuf field: teleport.lib.teleterm.v1.TargetHealth target_health = 9;
*/
targetHealth?: TargetHealth;
}
/**
* DatabaseServer (db_server) describes a database heartbeat signal
* reported from an agent (db_service) that is proxying
* the database.
*
* @generated from protobuf message teleport.lib.teleterm.v1.DatabaseServer
*/
export interface DatabaseServer {
/**
* @generated from protobuf field: string uri = 1;
*/
uri: string;
/**
* @generated from protobuf field: string hostname = 2;
*/
hostname: string;
/**
* @generated from protobuf field: string host_id = 3;
*/
hostId: string;
/**
* @generated from protobuf field: teleport.lib.teleterm.v1.TargetHealth target_health = 4;
*/
targetHealth?: TargetHealth;
}
// @generated message type with reflection information, may provide speed optimized methods
class Database$Type extends MessageType<Database> {
@@ -97,7 +129,8 @@ class Database$Type extends MessageType<Database> {
{ no: 5, name: "type", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 6, name: "hostname", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 7, name: "addr", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 8, name: "labels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Label }
{ no: 8, name: "labels", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Label },
{ no: 9, name: "target_health", kind: "message", T: () => TargetHealth }
]);
}
create(value?: PartialMessage<Database>): Database {
@@ -143,6 +176,9 @@ class Database$Type extends MessageType<Database> {
case /* repeated teleport.lib.teleterm.v1.Label labels */ 8:
message.labels.push(Label.internalBinaryRead(reader, reader.uint32(), options));
break;
case /* teleport.lib.teleterm.v1.TargetHealth target_health */ 9:
message.targetHealth = TargetHealth.internalBinaryRead(reader, reader.uint32(), options, message.targetHealth);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
@@ -179,6 +215,9 @@ class Database$Type extends MessageType<Database> {
/* repeated teleport.lib.teleterm.v1.Label labels = 8; */
for (let i = 0; i < message.labels.length; i++)
Label.internalBinaryWrite(message.labels[i], writer.tag(8, WireType.LengthDelimited).fork(), options).join();
/* teleport.lib.teleterm.v1.TargetHealth target_health = 9; */
if (message.targetHealth)
TargetHealth.internalBinaryWrite(message.targetHealth, writer.tag(9, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -189,3 +228,73 @@ class Database$Type extends MessageType<Database> {
* @generated MessageType for protobuf message teleport.lib.teleterm.v1.Database
*/
export const Database = new Database$Type();
// @generated message type with reflection information, may provide speed optimized methods
class DatabaseServer$Type extends MessageType<DatabaseServer> {
constructor() {
super("teleport.lib.teleterm.v1.DatabaseServer", [
{ no: 1, name: "uri", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "hostname", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "host_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 4, name: "target_health", kind: "message", T: () => TargetHealth }
]);
}
create(value?: PartialMessage<DatabaseServer>): DatabaseServer {
const message = globalThis.Object.create((this.messagePrototype!));
message.uri = "";
message.hostname = "";
message.hostId = "";
if (value !== undefined)
reflectionMergePartial<DatabaseServer>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DatabaseServer): DatabaseServer {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string uri */ 1:
message.uri = reader.string();
break;
case /* string hostname */ 2:
message.hostname = reader.string();
break;
case /* string host_id */ 3:
message.hostId = reader.string();
break;
case /* teleport.lib.teleterm.v1.TargetHealth target_health */ 4:
message.targetHealth = TargetHealth.internalBinaryRead(reader, reader.uint32(), options, message.targetHealth);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: DatabaseServer, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string uri = 1; */
if (message.uri !== "")
writer.tag(1, WireType.LengthDelimited).string(message.uri);
/* string hostname = 2; */
if (message.hostname !== "")
writer.tag(2, WireType.LengthDelimited).string(message.hostname);
/* string host_id = 3; */
if (message.hostId !== "")
writer.tag(3, WireType.LengthDelimited).string(message.hostId);
/* teleport.lib.teleterm.v1.TargetHealth target_health = 4; */
if (message.targetHealth)
TargetHealth.internalBinaryWrite(message.targetHealth, writer.tag(4, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message teleport.lib.teleterm.v1.DatabaseServer
*/
export const DatabaseServer = new DatabaseServer$Type();
+54 -37
View File
@@ -91,6 +91,8 @@ import type { GetAccessRequestsResponse } from "./service_pb";
import type { GetAccessRequestsRequest } from "./service_pb";
import type { GetServersResponse } from "./service_pb";
import type { GetServersRequest } from "./service_pb";
import type { ListDatabaseServersResponse } from "./service_pb";
import type { ListDatabaseServersRequest } from "./service_pb";
import type { ListDatabaseUsersResponse } from "./service_pb";
import type { ListDatabaseUsersRequest } from "./service_pb";
import type { StartHeadlessWatcherResponse } from "./service_pb";
@@ -151,6 +153,12 @@ export interface ITerminalServiceClient {
* @generated from protobuf rpc: ListDatabaseUsers(teleport.lib.teleterm.v1.ListDatabaseUsersRequest) returns (teleport.lib.teleterm.v1.ListDatabaseUsersResponse);
*/
listDatabaseUsers(input: ListDatabaseUsersRequest, options?: RpcOptions): UnaryCall<ListDatabaseUsersRequest, ListDatabaseUsersResponse>;
/**
* ListDatabaseServers lists allowed users for the given database based on the role set.
*
* @generated from protobuf rpc: ListDatabaseServers(teleport.lib.teleterm.v1.ListDatabaseServersRequest) returns (teleport.lib.teleterm.v1.ListDatabaseServersResponse);
*/
listDatabaseServers(input: ListDatabaseServersRequest, options?: RpcOptions): UnaryCall<ListDatabaseServersRequest, ListDatabaseServersResponse>;
/**
* GetServers returns filtered, sorted, and paginated servers
*
@@ -480,6 +488,15 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
const method = this.methods[4], opt = this._transport.mergeOptions(options);
return stackIntercept<ListDatabaseUsersRequest, ListDatabaseUsersResponse>("unary", this._transport, method, opt, input);
}
/**
* ListDatabaseServers lists allowed users for the given database based on the role set.
*
* @generated from protobuf rpc: ListDatabaseServers(teleport.lib.teleterm.v1.ListDatabaseServersRequest) returns (teleport.lib.teleterm.v1.ListDatabaseServersResponse);
*/
listDatabaseServers(input: ListDatabaseServersRequest, options?: RpcOptions): UnaryCall<ListDatabaseServersRequest, ListDatabaseServersResponse> {
const method = this.methods[5], opt = this._transport.mergeOptions(options);
return stackIntercept<ListDatabaseServersRequest, ListDatabaseServersResponse>("unary", this._transport, method, opt, input);
}
/**
* GetServers returns filtered, sorted, and paginated servers
*
@@ -489,7 +506,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetServers(teleport.lib.teleterm.v1.GetServersRequest) returns (teleport.lib.teleterm.v1.GetServersResponse);
*/
getServers(input: GetServersRequest, options?: RpcOptions): UnaryCall<GetServersRequest, GetServersResponse> {
const method = this.methods[5], opt = this._transport.mergeOptions(options);
const method = this.methods[6], opt = this._transport.mergeOptions(options);
return stackIntercept<GetServersRequest, GetServersResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -498,7 +515,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetAccessRequests(teleport.lib.teleterm.v1.GetAccessRequestsRequest) returns (teleport.lib.teleterm.v1.GetAccessRequestsResponse);
*/
getAccessRequests(input: GetAccessRequestsRequest, options?: RpcOptions): UnaryCall<GetAccessRequestsRequest, GetAccessRequestsResponse> {
const method = this.methods[6], opt = this._transport.mergeOptions(options);
const method = this.methods[7], opt = this._transport.mergeOptions(options);
return stackIntercept<GetAccessRequestsRequest, GetAccessRequestsResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -507,7 +524,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetAccessRequest(teleport.lib.teleterm.v1.GetAccessRequestRequest) returns (teleport.lib.teleterm.v1.GetAccessRequestResponse);
*/
getAccessRequest(input: GetAccessRequestRequest, options?: RpcOptions): UnaryCall<GetAccessRequestRequest, GetAccessRequestResponse> {
const method = this.methods[7], opt = this._transport.mergeOptions(options);
const method = this.methods[8], opt = this._transport.mergeOptions(options);
return stackIntercept<GetAccessRequestRequest, GetAccessRequestResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -516,7 +533,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: DeleteAccessRequest(teleport.lib.teleterm.v1.DeleteAccessRequestRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
deleteAccessRequest(input: DeleteAccessRequestRequest, options?: RpcOptions): UnaryCall<DeleteAccessRequestRequest, EmptyResponse> {
const method = this.methods[8], opt = this._transport.mergeOptions(options);
const method = this.methods[9], opt = this._transport.mergeOptions(options);
return stackIntercept<DeleteAccessRequestRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -525,7 +542,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: CreateAccessRequest(teleport.lib.teleterm.v1.CreateAccessRequestRequest) returns (teleport.lib.teleterm.v1.CreateAccessRequestResponse);
*/
createAccessRequest(input: CreateAccessRequestRequest, options?: RpcOptions): UnaryCall<CreateAccessRequestRequest, CreateAccessRequestResponse> {
const method = this.methods[9], opt = this._transport.mergeOptions(options);
const method = this.methods[10], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateAccessRequestRequest, CreateAccessRequestResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -534,7 +551,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: ReviewAccessRequest(teleport.lib.teleterm.v1.ReviewAccessRequestRequest) returns (teleport.lib.teleterm.v1.ReviewAccessRequestResponse);
*/
reviewAccessRequest(input: ReviewAccessRequestRequest, options?: RpcOptions): UnaryCall<ReviewAccessRequestRequest, ReviewAccessRequestResponse> {
const method = this.methods[10], opt = this._transport.mergeOptions(options);
const method = this.methods[11], opt = this._transport.mergeOptions(options);
return stackIntercept<ReviewAccessRequestRequest, ReviewAccessRequestResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -543,7 +560,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetRequestableRoles(teleport.lib.teleterm.v1.GetRequestableRolesRequest) returns (teleport.lib.teleterm.v1.GetRequestableRolesResponse);
*/
getRequestableRoles(input: GetRequestableRolesRequest, options?: RpcOptions): UnaryCall<GetRequestableRolesRequest, GetRequestableRolesResponse> {
const method = this.methods[11], opt = this._transport.mergeOptions(options);
const method = this.methods[12], opt = this._transport.mergeOptions(options);
return stackIntercept<GetRequestableRolesRequest, GetRequestableRolesResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -552,7 +569,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: AssumeRole(teleport.lib.teleterm.v1.AssumeRoleRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
assumeRole(input: AssumeRoleRequest, options?: RpcOptions): UnaryCall<AssumeRoleRequest, EmptyResponse> {
const method = this.methods[12], opt = this._transport.mergeOptions(options);
const method = this.methods[13], opt = this._transport.mergeOptions(options);
return stackIntercept<AssumeRoleRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -561,7 +578,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: PromoteAccessRequest(teleport.lib.teleterm.v1.PromoteAccessRequestRequest) returns (teleport.lib.teleterm.v1.PromoteAccessRequestResponse);
*/
promoteAccessRequest(input: PromoteAccessRequestRequest, options?: RpcOptions): UnaryCall<PromoteAccessRequestRequest, PromoteAccessRequestResponse> {
const method = this.methods[13], opt = this._transport.mergeOptions(options);
const method = this.methods[14], opt = this._transport.mergeOptions(options);
return stackIntercept<PromoteAccessRequestRequest, PromoteAccessRequestResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -570,7 +587,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetSuggestedAccessLists(teleport.lib.teleterm.v1.GetSuggestedAccessListsRequest) returns (teleport.lib.teleterm.v1.GetSuggestedAccessListsResponse);
*/
getSuggestedAccessLists(input: GetSuggestedAccessListsRequest, options?: RpcOptions): UnaryCall<GetSuggestedAccessListsRequest, GetSuggestedAccessListsResponse> {
const method = this.methods[14], opt = this._transport.mergeOptions(options);
const method = this.methods[15], opt = this._transport.mergeOptions(options);
return stackIntercept<GetSuggestedAccessListsRequest, GetSuggestedAccessListsResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -580,7 +597,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: ListKubernetesResources(teleport.lib.teleterm.v1.ListKubernetesResourcesRequest) returns (teleport.lib.teleterm.v1.ListKubernetesResourcesResponse);
*/
listKubernetesResources(input: ListKubernetesResourcesRequest, options?: RpcOptions): UnaryCall<ListKubernetesResourcesRequest, ListKubernetesResourcesResponse> {
const method = this.methods[15], opt = this._transport.mergeOptions(options);
const method = this.methods[16], opt = this._transport.mergeOptions(options);
return stackIntercept<ListKubernetesResourcesRequest, ListKubernetesResourcesResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -589,7 +606,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: AddCluster(teleport.lib.teleterm.v1.AddClusterRequest) returns (teleport.lib.teleterm.v1.Cluster);
*/
addCluster(input: AddClusterRequest, options?: RpcOptions): UnaryCall<AddClusterRequest, Cluster> {
const method = this.methods[16], opt = this._transport.mergeOptions(options);
const method = this.methods[17], opt = this._transport.mergeOptions(options);
return stackIntercept<AddClusterRequest, Cluster>("unary", this._transport, method, opt, input);
}
/**
@@ -598,7 +615,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: RemoveCluster(teleport.lib.teleterm.v1.RemoveClusterRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
removeCluster(input: RemoveClusterRequest, options?: RpcOptions): UnaryCall<RemoveClusterRequest, EmptyResponse> {
const method = this.methods[17], opt = this._transport.mergeOptions(options);
const method = this.methods[18], opt = this._transport.mergeOptions(options);
return stackIntercept<RemoveClusterRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -607,7 +624,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: ListGateways(teleport.lib.teleterm.v1.ListGatewaysRequest) returns (teleport.lib.teleterm.v1.ListGatewaysResponse);
*/
listGateways(input: ListGatewaysRequest, options?: RpcOptions): UnaryCall<ListGatewaysRequest, ListGatewaysResponse> {
const method = this.methods[18], opt = this._transport.mergeOptions(options);
const method = this.methods[19], opt = this._transport.mergeOptions(options);
return stackIntercept<ListGatewaysRequest, ListGatewaysResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -616,7 +633,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: CreateGateway(teleport.lib.teleterm.v1.CreateGatewayRequest) returns (teleport.lib.teleterm.v1.Gateway);
*/
createGateway(input: CreateGatewayRequest, options?: RpcOptions): UnaryCall<CreateGatewayRequest, Gateway> {
const method = this.methods[19], opt = this._transport.mergeOptions(options);
const method = this.methods[20], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateGatewayRequest, Gateway>("unary", this._transport, method, opt, input);
}
/**
@@ -625,7 +642,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: RemoveGateway(teleport.lib.teleterm.v1.RemoveGatewayRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
removeGateway(input: RemoveGatewayRequest, options?: RpcOptions): UnaryCall<RemoveGatewayRequest, EmptyResponse> {
const method = this.methods[20], opt = this._transport.mergeOptions(options);
const method = this.methods[21], opt = this._transport.mergeOptions(options);
return stackIntercept<RemoveGatewayRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -637,7 +654,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: SetGatewayTargetSubresourceName(teleport.lib.teleterm.v1.SetGatewayTargetSubresourceNameRequest) returns (teleport.lib.teleterm.v1.Gateway);
*/
setGatewayTargetSubresourceName(input: SetGatewayTargetSubresourceNameRequest, options?: RpcOptions): UnaryCall<SetGatewayTargetSubresourceNameRequest, Gateway> {
const method = this.methods[21], opt = this._transport.mergeOptions(options);
const method = this.methods[22], opt = this._transport.mergeOptions(options);
return stackIntercept<SetGatewayTargetSubresourceNameRequest, Gateway>("unary", this._transport, method, opt, input);
}
/**
@@ -647,7 +664,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: SetGatewayLocalPort(teleport.lib.teleterm.v1.SetGatewayLocalPortRequest) returns (teleport.lib.teleterm.v1.Gateway);
*/
setGatewayLocalPort(input: SetGatewayLocalPortRequest, options?: RpcOptions): UnaryCall<SetGatewayLocalPortRequest, Gateway> {
const method = this.methods[22], opt = this._transport.mergeOptions(options);
const method = this.methods[23], opt = this._transport.mergeOptions(options);
return stackIntercept<SetGatewayLocalPortRequest, Gateway>("unary", this._transport, method, opt, input);
}
/**
@@ -656,7 +673,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetAuthSettings(teleport.lib.teleterm.v1.GetAuthSettingsRequest) returns (teleport.lib.teleterm.v1.AuthSettings);
*/
getAuthSettings(input: GetAuthSettingsRequest, options?: RpcOptions): UnaryCall<GetAuthSettingsRequest, AuthSettings> {
const method = this.methods[23], opt = this._transport.mergeOptions(options);
const method = this.methods[24], opt = this._transport.mergeOptions(options);
return stackIntercept<GetAuthSettingsRequest, AuthSettings>("unary", this._transport, method, opt, input);
}
/**
@@ -666,7 +683,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetCluster(teleport.lib.teleterm.v1.GetClusterRequest) returns (teleport.lib.teleterm.v1.Cluster);
*/
getCluster(input: GetClusterRequest, options?: RpcOptions): UnaryCall<GetClusterRequest, Cluster> {
const method = this.methods[24], opt = this._transport.mergeOptions(options);
const method = this.methods[25], opt = this._transport.mergeOptions(options);
return stackIntercept<GetClusterRequest, Cluster>("unary", this._transport, method, opt, input);
}
/**
@@ -675,7 +692,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: Login(teleport.lib.teleterm.v1.LoginRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
login(input: LoginRequest, options?: RpcOptions): UnaryCall<LoginRequest, EmptyResponse> {
const method = this.methods[25], opt = this._transport.mergeOptions(options);
const method = this.methods[26], opt = this._transport.mergeOptions(options);
return stackIntercept<LoginRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -699,7 +716,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: LoginPasswordless(stream teleport.lib.teleterm.v1.LoginPasswordlessRequest) returns (stream teleport.lib.teleterm.v1.LoginPasswordlessResponse);
*/
loginPasswordless(options?: RpcOptions): DuplexStreamingCall<LoginPasswordlessRequest, LoginPasswordlessResponse> {
const method = this.methods[26], opt = this._transport.mergeOptions(options);
const method = this.methods[27], opt = this._transport.mergeOptions(options);
return stackIntercept<LoginPasswordlessRequest, LoginPasswordlessResponse>("duplex", this._transport, method, opt);
}
/**
@@ -708,7 +725,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: Logout(teleport.lib.teleterm.v1.LogoutRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
logout(input: LogoutRequest, options?: RpcOptions): UnaryCall<LogoutRequest, EmptyResponse> {
const method = this.methods[27], opt = this._transport.mergeOptions(options);
const method = this.methods[28], opt = this._transport.mergeOptions(options);
return stackIntercept<LogoutRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -717,7 +734,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: TransferFile(teleport.lib.teleterm.v1.FileTransferRequest) returns (stream teleport.lib.teleterm.v1.FileTransferProgress);
*/
transferFile(input: FileTransferRequest, options?: RpcOptions): ServerStreamingCall<FileTransferRequest, FileTransferProgress> {
const method = this.methods[28], opt = this._transport.mergeOptions(options);
const method = this.methods[29], opt = this._transport.mergeOptions(options);
return stackIntercept<FileTransferRequest, FileTransferProgress>("serverStreaming", this._transport, method, opt, input);
}
/**
@@ -726,7 +743,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: ReportUsageEvent(teleport.lib.teleterm.v1.ReportUsageEventRequest) returns (teleport.lib.teleterm.v1.EmptyResponse);
*/
reportUsageEvent(input: ReportUsageEventRequest, options?: RpcOptions): UnaryCall<ReportUsageEventRequest, EmptyResponse> {
const method = this.methods[29], opt = this._transport.mergeOptions(options);
const method = this.methods[30], opt = this._transport.mergeOptions(options);
return stackIntercept<ReportUsageEventRequest, EmptyResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -736,7 +753,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: UpdateHeadlessAuthenticationState(teleport.lib.teleterm.v1.UpdateHeadlessAuthenticationStateRequest) returns (teleport.lib.teleterm.v1.UpdateHeadlessAuthenticationStateResponse);
*/
updateHeadlessAuthenticationState(input: UpdateHeadlessAuthenticationStateRequest, options?: RpcOptions): UnaryCall<UpdateHeadlessAuthenticationStateRequest, UpdateHeadlessAuthenticationStateResponse> {
const method = this.methods[30], opt = this._transport.mergeOptions(options);
const method = this.methods[31], opt = this._transport.mergeOptions(options);
return stackIntercept<UpdateHeadlessAuthenticationStateRequest, UpdateHeadlessAuthenticationStateResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -747,7 +764,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: CreateConnectMyComputerRole(teleport.lib.teleterm.v1.CreateConnectMyComputerRoleRequest) returns (teleport.lib.teleterm.v1.CreateConnectMyComputerRoleResponse);
*/
createConnectMyComputerRole(input: CreateConnectMyComputerRoleRequest, options?: RpcOptions): UnaryCall<CreateConnectMyComputerRoleRequest, CreateConnectMyComputerRoleResponse> {
const method = this.methods[31], opt = this._transport.mergeOptions(options);
const method = this.methods[32], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateConnectMyComputerRoleRequest, CreateConnectMyComputerRoleResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -756,7 +773,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: CreateConnectMyComputerNodeToken(teleport.lib.teleterm.v1.CreateConnectMyComputerNodeTokenRequest) returns (teleport.lib.teleterm.v1.CreateConnectMyComputerNodeTokenResponse);
*/
createConnectMyComputerNodeToken(input: CreateConnectMyComputerNodeTokenRequest, options?: RpcOptions): UnaryCall<CreateConnectMyComputerNodeTokenRequest, CreateConnectMyComputerNodeTokenResponse> {
const method = this.methods[32], opt = this._transport.mergeOptions(options);
const method = this.methods[33], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateConnectMyComputerNodeTokenRequest, CreateConnectMyComputerNodeTokenResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -770,7 +787,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: WaitForConnectMyComputerNodeJoin(teleport.lib.teleterm.v1.WaitForConnectMyComputerNodeJoinRequest) returns (teleport.lib.teleterm.v1.WaitForConnectMyComputerNodeJoinResponse);
*/
waitForConnectMyComputerNodeJoin(input: WaitForConnectMyComputerNodeJoinRequest, options?: RpcOptions): UnaryCall<WaitForConnectMyComputerNodeJoinRequest, WaitForConnectMyComputerNodeJoinResponse> {
const method = this.methods[33], opt = this._transport.mergeOptions(options);
const method = this.methods[34], opt = this._transport.mergeOptions(options);
return stackIntercept<WaitForConnectMyComputerNodeJoinRequest, WaitForConnectMyComputerNodeJoinResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -779,7 +796,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: DeleteConnectMyComputerNode(teleport.lib.teleterm.v1.DeleteConnectMyComputerNodeRequest) returns (teleport.lib.teleterm.v1.DeleteConnectMyComputerNodeResponse);
*/
deleteConnectMyComputerNode(input: DeleteConnectMyComputerNodeRequest, options?: RpcOptions): UnaryCall<DeleteConnectMyComputerNodeRequest, DeleteConnectMyComputerNodeResponse> {
const method = this.methods[34], opt = this._transport.mergeOptions(options);
const method = this.methods[35], opt = this._transport.mergeOptions(options);
return stackIntercept<DeleteConnectMyComputerNodeRequest, DeleteConnectMyComputerNodeResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -788,7 +805,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetConnectMyComputerNodeName(teleport.lib.teleterm.v1.GetConnectMyComputerNodeNameRequest) returns (teleport.lib.teleterm.v1.GetConnectMyComputerNodeNameResponse);
*/
getConnectMyComputerNodeName(input: GetConnectMyComputerNodeNameRequest, options?: RpcOptions): UnaryCall<GetConnectMyComputerNodeNameRequest, GetConnectMyComputerNodeNameResponse> {
const method = this.methods[35], opt = this._transport.mergeOptions(options);
const method = this.methods[36], opt = this._transport.mergeOptions(options);
return stackIntercept<GetConnectMyComputerNodeNameRequest, GetConnectMyComputerNodeNameResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -797,7 +814,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: ListUnifiedResources(teleport.lib.teleterm.v1.ListUnifiedResourcesRequest) returns (teleport.lib.teleterm.v1.ListUnifiedResourcesResponse);
*/
listUnifiedResources(input: ListUnifiedResourcesRequest, options?: RpcOptions): UnaryCall<ListUnifiedResourcesRequest, ListUnifiedResourcesResponse> {
const method = this.methods[36], opt = this._transport.mergeOptions(options);
const method = this.methods[37], opt = this._transport.mergeOptions(options);
return stackIntercept<ListUnifiedResourcesRequest, ListUnifiedResourcesResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -806,7 +823,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetUserPreferences(teleport.lib.teleterm.v1.GetUserPreferencesRequest) returns (teleport.lib.teleterm.v1.GetUserPreferencesResponse);
*/
getUserPreferences(input: GetUserPreferencesRequest, options?: RpcOptions): UnaryCall<GetUserPreferencesRequest, GetUserPreferencesResponse> {
const method = this.methods[37], opt = this._transport.mergeOptions(options);
const method = this.methods[38], opt = this._transport.mergeOptions(options);
return stackIntercept<GetUserPreferencesRequest, GetUserPreferencesResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -816,7 +833,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: UpdateUserPreferences(teleport.lib.teleterm.v1.UpdateUserPreferencesRequest) returns (teleport.lib.teleterm.v1.UpdateUserPreferencesResponse);
*/
updateUserPreferences(input: UpdateUserPreferencesRequest, options?: RpcOptions): UnaryCall<UpdateUserPreferencesRequest, UpdateUserPreferencesResponse> {
const method = this.methods[38], opt = this._transport.mergeOptions(options);
const method = this.methods[39], opt = this._transport.mergeOptions(options);
return stackIntercept<UpdateUserPreferencesRequest, UpdateUserPreferencesResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -829,7 +846,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: AuthenticateWebDevice(teleport.lib.teleterm.v1.AuthenticateWebDeviceRequest) returns (teleport.lib.teleterm.v1.AuthenticateWebDeviceResponse);
*/
authenticateWebDevice(input: AuthenticateWebDeviceRequest, options?: RpcOptions): UnaryCall<AuthenticateWebDeviceRequest, AuthenticateWebDeviceResponse> {
const method = this.methods[39], opt = this._transport.mergeOptions(options);
const method = this.methods[40], opt = this._transport.mergeOptions(options);
return stackIntercept<AuthenticateWebDeviceRequest, AuthenticateWebDeviceResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -839,7 +856,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: GetApp(teleport.lib.teleterm.v1.GetAppRequest) returns (teleport.lib.teleterm.v1.GetAppResponse);
*/
getApp(input: GetAppRequest, options?: RpcOptions): UnaryCall<GetAppRequest, GetAppResponse> {
const method = this.methods[40], opt = this._transport.mergeOptions(options);
const method = this.methods[41], opt = this._transport.mergeOptions(options);
return stackIntercept<GetAppRequest, GetAppResponse>("unary", this._transport, method, opt, input);
}
/**
@@ -848,7 +865,7 @@ export class TerminalServiceClient implements ITerminalServiceClient, ServiceInf
* @generated from protobuf rpc: ConnectToDesktop(stream teleport.lib.teleterm.v1.ConnectToDesktopRequest) returns (stream teleport.lib.teleterm.v1.ConnectToDesktopResponse);
*/
connectToDesktop(options?: RpcOptions): DuplexStreamingCall<ConnectToDesktopRequest, ConnectToDesktopResponse> {
const method = this.methods[41], opt = this._transport.mergeOptions(options);
const method = this.methods[42], opt = this._transport.mergeOptions(options);
return stackIntercept<ConnectToDesktopRequest, ConnectToDesktopResponse>("duplex", this._transport, method, opt);
}
}
@@ -86,6 +86,8 @@ import { GetAccessRequestsResponse } from "./service_pb";
import { GetAccessRequestsRequest } from "./service_pb";
import { GetServersResponse } from "./service_pb";
import { GetServersRequest } from "./service_pb";
import { ListDatabaseServersResponse } from "./service_pb";
import { ListDatabaseServersRequest } from "./service_pb";
import { ListDatabaseUsersResponse } from "./service_pb";
import { ListDatabaseUsersRequest } from "./service_pb";
import { StartHeadlessWatcherResponse } from "./service_pb";
@@ -144,6 +146,12 @@ export interface ITerminalService extends grpc.UntypedServiceImplementation {
* @generated from protobuf rpc: ListDatabaseUsers(teleport.lib.teleterm.v1.ListDatabaseUsersRequest) returns (teleport.lib.teleterm.v1.ListDatabaseUsersResponse);
*/
listDatabaseUsers: grpc.handleUnaryCall<ListDatabaseUsersRequest, ListDatabaseUsersResponse>;
/**
* ListDatabaseServers lists allowed users for the given database based on the role set.
*
* @generated from protobuf rpc: ListDatabaseServers(teleport.lib.teleterm.v1.ListDatabaseServersRequest) returns (teleport.lib.teleterm.v1.ListDatabaseServersResponse);
*/
listDatabaseServers: grpc.handleUnaryCall<ListDatabaseServersRequest, ListDatabaseServersResponse>;
/**
* GetServers returns filtered, sorted, and paginated servers
*
@@ -467,6 +475,16 @@ export const terminalServiceDefinition: grpc.ServiceDefinition<ITerminalService>
responseSerialize: value => Buffer.from(ListDatabaseUsersResponse.toBinary(value)),
requestSerialize: value => Buffer.from(ListDatabaseUsersRequest.toBinary(value))
},
listDatabaseServers: {
path: "/teleport.lib.teleterm.v1.TerminalService/ListDatabaseServers",
originalName: "ListDatabaseServers",
requestStream: false,
responseStream: false,
responseDeserialize: bytes => ListDatabaseServersResponse.fromBinary(bytes),
requestDeserialize: bytes => ListDatabaseServersRequest.fromBinary(bytes),
responseSerialize: value => Buffer.from(ListDatabaseServersResponse.toBinary(value)),
requestSerialize: value => Buffer.from(ListDatabaseServersRequest.toBinary(value))
},
getServers: {
path: "/teleport.lib.teleterm.v1.TerminalService/GetServers",
originalName: "GetServers",
+237 -1
View File
@@ -43,6 +43,7 @@ import { Kube } from "./kube_pb";
import { Database } from "./database_pb";
import { Server } from "./server_pb";
import { Gateway } from "./gateway_pb";
import { DatabaseServer } from "./database_pb";
import { Cluster } from "./cluster_pb";
import { KubeResource } from "./kube_pb";
import { AccessList } from "../../../accesslist/v1/accesslist_pb";
@@ -700,6 +701,60 @@ export interface ListDatabaseUsersResponse {
*/
users: string[];
}
/**
* ListResourcesParams describes different types of params
* that can be applied when sending a request to a method that
* uses the ListResources API underneath.
*
* @generated from protobuf message teleport.lib.teleterm.v1.ListResourcesParams
*/
export interface ListResourcesParams {
/**
* @generated from protobuf field: string start_key = 1;
*/
startKey: string;
/**
* @generated from protobuf field: int32 limit = 2;
*/
limit: number;
/**
* @generated from protobuf field: string predicate_expression = 3;
*/
predicateExpression: string;
/**
* UseSearchAsRoles indicates that the response should include all resources
* the caller is able to request access to using search_as_roles
*
* @generated from protobuf field: bool use_search_as_roles = 4;
*/
useSearchAsRoles: boolean;
}
/**
* @generated from protobuf message teleport.lib.teleterm.v1.ListDatabaseServersRequest
*/
export interface ListDatabaseServersRequest {
/**
* @generated from protobuf field: string cluster_uri = 1;
*/
clusterUri: string;
/**
* @generated from protobuf field: teleport.lib.teleterm.v1.ListResourcesParams params = 2;
*/
params?: ListResourcesParams;
}
/**
* @generated from protobuf message teleport.lib.teleterm.v1.ListDatabaseServersResponse
*/
export interface ListDatabaseServersResponse {
/**
* @generated from protobuf field: repeated teleport.lib.teleterm.v1.DatabaseServer resources = 1;
*/
resources: DatabaseServer[];
/**
* @generated from protobuf field: string next_key = 2;
*/
nextKey: string;
}
/**
* @generated from protobuf message teleport.lib.teleterm.v1.CreateGatewayRequest
*/
@@ -1046,7 +1101,7 @@ export interface ListUnifiedResourcesResponse {
*/
resources: PaginatedResource[];
/**
* A key to use as start_key in a ListResourcesRequest to continue retrieving
* A key to use as start_key in a ListUnifiedResourcesRequest to continue retrieving
* the next pages. If it is empty, there are no more pages.
*
* @generated from protobuf field: string next_key = 2;
@@ -3539,6 +3594,186 @@ class ListDatabaseUsersResponse$Type extends MessageType<ListDatabaseUsersRespon
*/
export const ListDatabaseUsersResponse = new ListDatabaseUsersResponse$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListResourcesParams$Type extends MessageType<ListResourcesParams> {
constructor() {
super("teleport.lib.teleterm.v1.ListResourcesParams", [
{ no: 1, name: "start_key", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "limit", kind: "scalar", T: 5 /*ScalarType.INT32*/ },
{ no: 3, name: "predicate_expression", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 4, name: "use_search_as_roles", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
]);
}
create(value?: PartialMessage<ListResourcesParams>): ListResourcesParams {
const message = globalThis.Object.create((this.messagePrototype!));
message.startKey = "";
message.limit = 0;
message.predicateExpression = "";
message.useSearchAsRoles = false;
if (value !== undefined)
reflectionMergePartial<ListResourcesParams>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListResourcesParams): ListResourcesParams {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string start_key */ 1:
message.startKey = reader.string();
break;
case /* int32 limit */ 2:
message.limit = reader.int32();
break;
case /* string predicate_expression */ 3:
message.predicateExpression = reader.string();
break;
case /* bool use_search_as_roles */ 4:
message.useSearchAsRoles = reader.bool();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListResourcesParams, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string start_key = 1; */
if (message.startKey !== "")
writer.tag(1, WireType.LengthDelimited).string(message.startKey);
/* int32 limit = 2; */
if (message.limit !== 0)
writer.tag(2, WireType.Varint).int32(message.limit);
/* string predicate_expression = 3; */
if (message.predicateExpression !== "")
writer.tag(3, WireType.LengthDelimited).string(message.predicateExpression);
/* bool use_search_as_roles = 4; */
if (message.useSearchAsRoles !== false)
writer.tag(4, WireType.Varint).bool(message.useSearchAsRoles);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message teleport.lib.teleterm.v1.ListResourcesParams
*/
export const ListResourcesParams = new ListResourcesParams$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListDatabaseServersRequest$Type extends MessageType<ListDatabaseServersRequest> {
constructor() {
super("teleport.lib.teleterm.v1.ListDatabaseServersRequest", [
{ no: 1, name: "cluster_uri", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "params", kind: "message", T: () => ListResourcesParams }
]);
}
create(value?: PartialMessage<ListDatabaseServersRequest>): ListDatabaseServersRequest {
const message = globalThis.Object.create((this.messagePrototype!));
message.clusterUri = "";
if (value !== undefined)
reflectionMergePartial<ListDatabaseServersRequest>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListDatabaseServersRequest): ListDatabaseServersRequest {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string cluster_uri */ 1:
message.clusterUri = reader.string();
break;
case /* teleport.lib.teleterm.v1.ListResourcesParams params */ 2:
message.params = ListResourcesParams.internalBinaryRead(reader, reader.uint32(), options, message.params);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListDatabaseServersRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string cluster_uri = 1; */
if (message.clusterUri !== "")
writer.tag(1, WireType.LengthDelimited).string(message.clusterUri);
/* teleport.lib.teleterm.v1.ListResourcesParams params = 2; */
if (message.params)
ListResourcesParams.internalBinaryWrite(message.params, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message teleport.lib.teleterm.v1.ListDatabaseServersRequest
*/
export const ListDatabaseServersRequest = new ListDatabaseServersRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListDatabaseServersResponse$Type extends MessageType<ListDatabaseServersResponse> {
constructor() {
super("teleport.lib.teleterm.v1.ListDatabaseServersResponse", [
{ no: 1, name: "resources", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => DatabaseServer },
{ no: 2, name: "next_key", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value?: PartialMessage<ListDatabaseServersResponse>): ListDatabaseServersResponse {
const message = globalThis.Object.create((this.messagePrototype!));
message.resources = [];
message.nextKey = "";
if (value !== undefined)
reflectionMergePartial<ListDatabaseServersResponse>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListDatabaseServersResponse): ListDatabaseServersResponse {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* repeated teleport.lib.teleterm.v1.DatabaseServer resources */ 1:
message.resources.push(DatabaseServer.internalBinaryRead(reader, reader.uint32(), options));
break;
case /* string next_key */ 2:
message.nextKey = reader.string();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListDatabaseServersResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* repeated teleport.lib.teleterm.v1.DatabaseServer resources = 1; */
for (let i = 0; i < message.resources.length; i++)
DatabaseServer.internalBinaryWrite(message.resources[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
/* string next_key = 2; */
if (message.nextKey !== "")
writer.tag(2, WireType.LengthDelimited).string(message.nextKey);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message teleport.lib.teleterm.v1.ListDatabaseServersResponse
*/
export const ListDatabaseServersResponse = new ListDatabaseServersResponse$Type();
// @generated message type with reflection information, may provide speed optimized methods
class CreateGatewayRequest$Type extends MessageType<CreateGatewayRequest> {
constructor() {
super("teleport.lib.teleterm.v1.CreateGatewayRequest", [
@@ -5580,6 +5815,7 @@ export const TerminalService = new ServiceType("teleport.lib.teleterm.v1.Termina
{ name: "ListLeafClusters", options: {}, I: ListLeafClustersRequest, O: ListClustersResponse },
{ name: "StartHeadlessWatcher", options: {}, I: StartHeadlessWatcherRequest, O: StartHeadlessWatcherResponse },
{ name: "ListDatabaseUsers", options: {}, I: ListDatabaseUsersRequest, O: ListDatabaseUsersResponse },
{ name: "ListDatabaseServers", options: {}, I: ListDatabaseServersRequest, O: ListDatabaseServersResponse },
{ name: "GetServers", options: {}, I: GetServersRequest, O: GetServersResponse },
{ name: "GetAccessRequests", options: {}, I: GetAccessRequestsRequest, O: GetAccessRequestsResponse },
{ name: "GetAccessRequest", options: {}, I: GetAccessRequestRequest, O: GetAccessRequestResponse },
+108
View File
@@ -0,0 +1,108 @@
/* eslint-disable */
// @generated by protobuf-ts 2.9.3 with parameter eslint_disable,add_pb_suffix,server_grpc1,ts_nocheck
// @generated from protobuf file "teleport/lib/teleterm/v1/target_health.proto" (package "teleport.lib.teleterm.v1", syntax proto3)
// tslint:disable
// @ts-nocheck
//
//
// Teleport
// Copyright (C) 2025 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
/**
* TargetHealth describes the health status of network connectivity between
* an agent and a resource.
*
* @generated from protobuf message teleport.lib.teleterm.v1.TargetHealth
*/
export interface TargetHealth {
/**
* status is the health status, one of "", "unknown", "healthy", "unhealthy".
*
* @generated from protobuf field: string status = 1;
*/
status: string;
/**
* error is the health check error observed, when
* "status" field != "healthy".
*
* @generated from protobuf field: string error = 2;
*/
error: string;
}
// @generated message type with reflection information, may provide speed optimized methods
class TargetHealth$Type extends MessageType<TargetHealth> {
constructor() {
super("teleport.lib.teleterm.v1.TargetHealth", [
{ no: 1, name: "status", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "error", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value?: PartialMessage<TargetHealth>): TargetHealth {
const message = globalThis.Object.create((this.messagePrototype!));
message.status = "";
message.error = "";
if (value !== undefined)
reflectionMergePartial<TargetHealth>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: TargetHealth): TargetHealth {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string status */ 1:
message.status = reader.string();
break;
case /* string error */ 2:
message.error = reader.string();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: TargetHealth, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string status = 1; */
if (message.status !== "")
writer.tag(1, WireType.LengthDelimited).string(message.status);
/* string error = 2; */
if (message.error !== "")
writer.tag(2, WireType.LengthDelimited).string(message.error);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message teleport.lib.teleterm.v1.TargetHealth
*/
export const TargetHealth = new TargetHealth$Type();
+23
View File
@@ -30,6 +30,8 @@ var pathServers = urlpath.New("/clusters/:cluster/servers/:serverUUID")
var pathLeafServers = urlpath.New("/clusters/:cluster/leaves/:leaf/servers/:serverUUID")
var pathDbs = urlpath.New("/clusters/:cluster/dbs/:dbName")
var pathLeafDbs = urlpath.New("/clusters/:cluster/leaves/:leaf/dbs/:dbName")
var pathDbServers = urlpath.New("/clusters/:cluster/db_servers/:dbServer")
var pathLeafDbServers = urlpath.New("/clusters/:cluster/leaves/:leaf/db_servers/:dbServer")
var pathKubes = urlpath.New("/clusters/:cluster/kubes/:kubeName")
var pathLeafKubes = urlpath.New("/clusters/:cluster/leaves/:leaf/kubes/:kubeName")
var pathKubeResourceNamespace = urlpath.New("/clusters/:cluster/kubes/:kubeName/namespaces/:kubeNamespaceName")
@@ -111,6 +113,21 @@ func (r ResourceURI) GetDbName() string {
return ""
}
// GetDBServerName extracts the database server name from r. Returns an empty string if path is not a db_servers URI.
func (r ResourceURI) GetDBServerName() string {
result, ok := pathDbServers.Match(r.path)
if ok {
return result.Params["dbServer"]
}
result, ok = pathLeafDbServers.Match(r.path)
if ok {
return result.Params["dbServer"]
}
return ""
}
// GetKubeName extracts the kube name from r. Returns an empty string if path is not a kube URI.
func (r ResourceURI) GetKubeName() string {
result, ok := pathKubes.Match(r.path)
@@ -207,6 +224,12 @@ func (r ResourceURI) AppendServer(id string) ResourceURI {
return r
}
// AppendDBServer appends db_server segment to the URI
func (r ResourceURI) AppendDBServer(id string) ResourceURI {
r.path = fmt.Sprintf("%v/db_servers/%v", r.path, id)
return r
}
// AppendLeafCluster appends leaf cluster segment to the URI if name is not empty.
func (r ResourceURI) AppendLeafCluster(name string) ResourceURI {
if name == "" {
+50
View File
@@ -44,6 +44,10 @@ func TestString(t *testing.T) {
uri.NewClusterURI("teleport.sh").AppendDB("dbhost1"),
"/clusters/teleport.sh/dbs/dbhost1",
},
{
uri.NewClusterURI("teleport.sh").AppendDBServer("dbserver1"),
"/clusters/teleport.sh/db_servers/dbserver1",
},
{
uri.NewClusterURI("teleport.sh").AppendKube("kube-cluster-name").AppendKubeResourceNamespace("namespace-name"),
"/clusters/teleport.sh/kubes/kube-cluster-name/namespaces/namespace-name",
@@ -134,6 +138,52 @@ func TestGetDbName(t *testing.T) {
}
}
func TestGetDbServerName(t *testing.T) {
tests := []struct {
name string
in uri.ResourceURI
out string
}{
{
name: "returns root cluster db_server name",
in: uri.NewClusterURI("foo").AppendDBServer("postgres"),
out: "postgres",
},
{
name: "returns leaf cluster db_server name",
in: uri.NewClusterURI("foo").AppendLeafCluster("bar").AppendDBServer("postgres"),
out: "postgres",
},
{
name: "returns empty string when given root cluster URI",
in: uri.NewClusterURI("foo"),
out: "",
},
{
name: "returns empty string when given leaf cluster URI",
in: uri.NewClusterURI("foo").AppendLeafCluster("bar"),
out: "",
},
{
name: "returns empty string when given root cluster non-db resource URI",
in: uri.NewClusterURI("foo").AppendKube("k8s"),
out: "",
},
{
name: "returns empty string when given leaf cluster non-db resource URI",
in: uri.NewClusterURI("foo").AppendLeafCluster("bar").AppendKube("k8s"),
out: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := tt.in.GetDBServerName()
require.Equal(t, tt.out, out)
})
}
}
func TestGetKubeName(t *testing.T) {
tests := []struct {
name string
@@ -54,6 +54,23 @@ func (s *Handler) ListDatabaseUsers(ctx context.Context, req *api.ListDatabaseUs
}, nil
}
// ListDatabaseServers returns a paginated list of database servers (resource kind "db_server").
func (s *Handler) ListDatabaseServers(ctx context.Context, req *api.ListDatabaseServersRequest) (*api.ListDatabaseServersResponse, error) {
resp, err := s.DaemonService.ListDatabaseServers(ctx, req)
if err != nil {
return nil, trace.Wrap(err)
}
response := &api.ListDatabaseServersResponse{
NextKey: resp.NextKey,
}
for _, server := range resp.Servers {
response.Resources = append(response.Resources, newAPIDatabaseServer(server))
}
return response, nil
}
func newAPIDatabase(db clusters.Database) *api.Database {
apiLabels := makeAPILabels(ui.MakeLabelsWithoutInternalPrefixes(db.GetAllLabels()))
@@ -64,5 +81,21 @@ func newAPIDatabase(db clusters.Database) *api.Database {
Protocol: db.GetProtocol(),
Type: db.GetType(),
Labels: apiLabels,
TargetHealth: &api.TargetHealth{
Status: db.TargetHealth.Status,
Error: db.TargetHealth.TransitionError,
},
}
}
func newAPIDatabaseServer(dbServer clusters.DatabaseServer) *api.DatabaseServer {
return &api.DatabaseServer{
Uri: dbServer.URI.String(),
Hostname: dbServer.GetHostname(),
HostId: dbServer.GetHostID(),
TargetHealth: &api.TargetHealth{
Status: dbServer.GetTargetHealth().Status,
Error: dbServer.GetTargetHealth().TransitionError,
},
}
}
@@ -29,6 +29,7 @@ import (
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/types"
api "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/client/db/dbcmd"
@@ -43,6 +44,18 @@ type Database struct {
// URI is the database URI
URI uri.ResourceURI
types.Database
// TargetHealth describes the health status of network connectivity
// of the db_server that is serving this database.
TargetHealth types.TargetHealth
}
// DatabaseServer (db_server) describes a database heartbeat signal
// reported from an agent (db_service) that is proxying
// the database.
type DatabaseServer struct {
// URI is the db_servers URI
URI uri.ResourceURI
types.DatabaseServer
}
// GetDatabase returns a database
@@ -131,6 +144,27 @@ func (c *Cluster) GetAllowedDatabaseUsers(ctx context.Context, authClient authcl
return dbUsers.Allowed(), nil
}
// ListDatabaseServers returns a paginated list of database servers (resource kind "db_server").
func (c *Cluster) ListDatabaseServers(ctx context.Context, params *api.ListResourcesParams, authClient authclient.ClientI) (*GetDatabaseServersResponse, error) {
page, err := listResources[types.DatabaseServer](ctx, params, authClient, types.KindDatabaseServer)
if err != nil {
return nil, trace.Wrap(err)
}
results := make([]DatabaseServer, 0, len(page.Resources))
for _, server := range page.Resources {
results = append(results, DatabaseServer{
URI: c.URI.AppendDBServer(server.GetName()),
DatabaseServer: server,
})
}
return &GetDatabaseServersResponse{
Servers: results,
NextKey: page.NextKey,
}, nil
}
type GetDatabasesResponse struct {
Databases []Database
// StartKey is the next key to use as a starting point.
@@ -139,6 +173,11 @@ type GetDatabasesResponse struct {
TotalCount int
}
type GetDatabaseServersResponse struct {
Servers []DatabaseServer
NextKey string
}
// NewDBCLICmdBuilder creates a dbcmd.CLICommandBuilder with provided cluster,
// db route, and options.
func NewDBCLICmdBuilder(cluster *Cluster, routeToDb tlsca.RouteToDatabase, options ...dbcmd.ConnectCommandFunc) *dbcmd.CLICommandBuilder {
@@ -0,0 +1,61 @@
/*
* Teleport
* Copyright (C) 2025 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package clusters
import (
"context"
"github.com/gravitational/trace"
apiclient "github.com/gravitational/teleport/api/client"
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/types"
api "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1"
"github.com/gravitational/teleport/lib/auth/authclient"
)
// listResources returns a paginated list of requested resourceKind (singular kind).
// Unlike unified resources, this request does not support multiple kinds in a single response.
// listResources supports querying for resource kinds that are not supported by unified resources.
// In addition, listResources does not de-duplicate resources like ListUnifiedResources does.
func listResources[T types.ResourceWithLabels](ctx context.Context, params *api.ListResourcesParams, authClient authclient.ClientI, resourceKind string) (apiclient.ResourcePage[T], error) {
var (
page apiclient.ResourcePage[T]
err error
)
req := &proto.ListResourcesRequest{
ResourceType: resourceKind,
Limit: params.Limit,
StartKey: params.StartKey,
PredicateExpression: params.PredicateExpression,
UseSearchAsRoles: params.UseSearchAsRoles,
}
err = AddMetadataToRetryableError(ctx, func() error {
page, err = apiclient.GetResourcePage[T](ctx, authClient, req)
if err != nil {
return trace.Wrap(err)
}
return nil
})
return page, trace.Wrap(err)
}
+21
View File
@@ -905,6 +905,27 @@ func (s *Service) ListKubernetesResources(ctx context.Context, clusterURI uri.Re
return resources, trace.Wrap(err)
}
// ListDatabaseServers returns a paginated list of database servers (resource kind "db_server").
func (s *Service) ListDatabaseServers(ctx context.Context, req *api.ListDatabaseServersRequest) (*clusters.GetDatabaseServersResponse, error) {
clusterURI, err := uri.Parse(req.GetClusterUri())
if err != nil {
return nil, trace.Wrap(err)
}
cluster, _, err := s.ResolveClusterURI(clusterURI)
if err != nil {
return nil, trace.Wrap(err)
}
proxyClient, err := s.GetCachedClient(ctx, clusterURI)
if err != nil {
return nil, trace.Wrap(err)
}
response, err := cluster.ListDatabaseServers(ctx, req.GetParams(), proxyClient.CurrentCluster())
return response, trace.Wrap(err)
}
func (s *Service) ReportUsageEvent(req *api.ReportUsageEventRequest) error {
prehogEvent, err := usagereporter.GetAnonymizedPrehogEvent(req)
if err != nil {
@@ -77,8 +77,9 @@ func List(ctx context.Context, cluster *clusters.Cluster, client apiclient.ListU
db := r.GetDatabase()
response.Resources = append(response.Resources, UnifiedResource{
Database: &clusters.Database{
URI: cluster.URI.AppendDB(db.GetName()),
Database: db,
URI: cluster.URI.AppendDB(db.GetName()),
Database: db,
TargetHealth: r.GetTargetHealth(),
},
RequiresRequest: requiresRequest,
})
+14 -1
View File
@@ -21,10 +21,11 @@ syntax = "proto3";
package teleport.lib.teleterm.v1;
import "teleport/lib/teleterm/v1/label.proto";
import "teleport/lib/teleterm/v1/target_health.proto";
option go_package = "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1;teletermv1";
// Database describes a database
// Database describes a database (resource kind "db")
message Database {
// uri is the cluster resource URI
string uri = 1;
@@ -42,4 +43,16 @@ message Database {
string addr = 7;
// labels is a list of labels for this database
repeated Label labels = 8;
// target_health of the "db_server" that is serving this database.
TargetHealth target_health = 9;
}
// DatabaseServer (db_server) describes a database heartbeat signal
// reported from an agent (db_service) that is proxying
// the database.
message DatabaseServer {
string uri = 1;
string hostname = 2;
string host_id = 3;
TargetHealth target_health = 4;
}
+25 -1
View File
@@ -64,6 +64,8 @@ service TerminalService {
rpc StartHeadlessWatcher(StartHeadlessWatcherRequest) returns (StartHeadlessWatcherResponse);
// ListDatabaseUsers lists allowed users for the given database based on the role set.
rpc ListDatabaseUsers(ListDatabaseUsersRequest) returns (ListDatabaseUsersResponse);
// ListDatabaseServers lists allowed users for the given database based on the role set.
rpc ListDatabaseServers(ListDatabaseServersRequest) returns (ListDatabaseServersResponse);
// GetServers returns filtered, sorted, and paginated servers
//
// Deprecated: Use ListUnifiedResources instead.
@@ -474,6 +476,28 @@ message ListDatabaseUsersResponse {
repeated string users = 1;
}
// ListResourcesParams describes different types of params
// that can be applied when sending a request to a method that
// uses the ListResources API underneath.
message ListResourcesParams {
string start_key = 1;
int32 limit = 2;
string predicate_expression = 3;
// UseSearchAsRoles indicates that the response should include all resources
// the caller is able to request access to using search_as_roles
bool use_search_as_roles = 4;
}
message ListDatabaseServersRequest {
string cluster_uri = 1;
ListResourcesParams params = 2;
}
message ListDatabaseServersResponse {
repeated DatabaseServer resources = 1;
string next_key = 2;
}
message CreateGatewayRequest {
string target_uri = 1;
string target_user = 2;
@@ -615,7 +639,7 @@ message SortBy {
message ListUnifiedResourcesResponse {
repeated PaginatedResource resources = 1;
// A key to use as start_key in a ListResourcesRequest to continue retrieving
// A key to use as start_key in a ListUnifiedResourcesRequest to continue retrieving
// the next pages. If it is empty, there are no more pages.
string next_key = 2;
}
@@ -0,0 +1,33 @@
/*
* Teleport
* Copyright (C) 2025 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
syntax = "proto3";
package teleport.lib.teleterm.v1;
option go_package = "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1;teletermv1";
// TargetHealth describes the health status of network connectivity between
// an agent and a resource.
message TargetHealth {
// status is the health status, one of "", "unknown", "healthy", "unhealthy".
string status = 1;
// error is the health check error observed, when
// "status" field != "healthy".
string error = 2;
}
@@ -618,10 +618,7 @@ export function UnifiedResources(props: UnifiedResourcesProps) {
},
}),
key: generateUnifiedResourceKey(resource),
// TODO(kimlisa): teleterm will pass this field as "null"
// to add support later.
onShowStatusInfo: () =>
onShowStatusInfo ? onShowStatusInfo(resource) : null,
onShowStatusInfo: () => onShowStatusInfo(resource),
showingStatusInfo:
infoGuideConfig?.id &&
infoGuideConfig.id === getResourceId(resource),
@@ -24,7 +24,6 @@ import {
} from 'shared/components/UnifiedResources';
import { UnhealthyStatusInfo } from 'shared/components/UnifiedResources/shared/StatusInfo';
import { ResourcesResponse } from 'teleport/services/agents';
import { fetchDatabaseServers } from 'teleport/services/databases/databases';
export function StatusInfo({
@@ -41,12 +40,10 @@ export function StatusInfo({
fetch: fetchResourceServers,
resources: resourceServers,
attempt: fetchResourceServersAttempt,
} = useResourceServersFetch({
} = useResourceServersFetch<SharedResourceServer>({
fetchFunc: async (params, signal) => {
let response: ResourcesResponse<SharedResourceServer>;
if (resource.kind === 'db') {
const resp = await fetchDatabaseServers({
const response = await fetchDatabaseServers({
clusterId,
params: {
...params,
@@ -55,17 +52,15 @@ export function StatusInfo({
},
signal,
});
const servers: DatabaseServer[] = resp.agents.map(d => ({
const servers: DatabaseServer[] = response.agents.map(d => ({
kind: 'db_server',
...d,
}));
response = {
return {
agents: servers,
startKey: resp.startKey,
startKey: response.startKey,
};
}
return response;
},
});
@@ -95,6 +95,8 @@ export class MockTshClient implements TshdClient {
new MockedUnaryCall({ resources: [], nextKey: '' });
listKubernetesResources = () =>
new MockedUnaryCall({ resources: [], nextKey: '' });
listDatabaseServers = () =>
new MockedUnaryCall({ resources: [], nextKey: '' });
getUserPreferences = () =>
new MockedUnaryCall({
userPreferences: {
@@ -19,6 +19,7 @@
import { useEffect } from 'react';
import styled from 'styled-components';
import { MockedUnaryCall } from 'teleterm/services/tshd/cloneableClient';
import {
leafClusterUri,
makeAcl,
@@ -86,6 +87,17 @@ export const OnlineLoadedResources = () => {
resource: makeDatabase(),
requiresRequest: false,
},
{
kind: 'database',
resource: makeDatabase({
name: 'unhealthy-database',
targetHealth: {
status: 'unhealthy',
error: 'some unhealthy error message',
},
}),
requiresRequest: false,
},
{
kind: 'kube',
resource: makeKube(),
@@ -304,6 +316,28 @@ function renderState({
? listUnifiedResources(params, abortSignal)
: Promise.reject('No fetchServersPromise passed');
appContext.tshd.listDatabaseServers = () =>
new MockedUnaryCall({
resources: [
{
hostname: 'some-hostname-1',
hostId: 'some-host-id-1',
uri: 'some-uri-1',
targetHealth: { status: 'unhealthy', error: 'some unhealthy error' },
},
{
hostname: 'some-hostname-2',
hostId: 'some-host-id-2',
uri: 'some-uri-2',
targetHealth: {
status: 'unhealthy',
error: 'some other unhealthy error',
},
},
],
nextKey: '',
});
return (
<AppContextProvider value={appContext}>
<ConnectionsContextProvider>
@@ -0,0 +1,85 @@
/**
* Teleport
* Copyright (C) 2025 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {
DatabaseServer,
ResourceStatus,
SharedResourceServer,
UnifiedResourceDefinition,
useResourceServersFetch,
} from 'shared/components/UnifiedResources';
import { UnhealthyStatusInfo } from 'shared/components/UnifiedResources/shared/StatusInfo';
import { cloneAbortSignal } from 'teleterm/services/tshd/cloneableClient';
import { useAppContext } from 'teleterm/ui/appContextProvider';
export function StatusInfo({
resource,
clusterUri,
}: {
/**
* the resource the user selected to look into the status of
*/
resource: UnifiedResourceDefinition;
clusterUri: string;
}) {
const ctx = useAppContext();
const {
fetch: fetchResourceServers,
resources: resourceServers,
attempt: fetchResourceServersAttempt,
} = useResourceServersFetch<SharedResourceServer>({
fetchFunc: async (params, signal) => {
if (resource.kind === 'db') {
const { response } = await ctx.tshd.listDatabaseServers(
{
clusterUri,
params: {
...params,
useSearchAsRoles: resource.requiresRequest ? true : false,
predicateExpression: `name == "${resource.name}"`,
},
},
{ abort: cloneAbortSignal(signal) }
);
const servers: DatabaseServer[] = response.resources.map(d => ({
kind: 'db_server',
hostname: d.hostname,
hostId: d.hostId,
targetHealth: d.targetHealth && {
status: d.targetHealth.status as ResourceStatus,
error: d.targetHealth.error,
},
}));
return {
agents: servers,
startKey: response.nextKey,
};
}
},
});
return (
<UnhealthyStatusInfo
resource={resource}
fetch={fetchResourceServers}
servers={resourceServers}
attempt={fetchResourceServersAttempt}
/>
);
}
@@ -37,12 +37,18 @@ import {
import {
getResourceAvailabilityFilter,
ResourceAvailabilityFilter,
ResourceStatus,
SharedUnifiedResource,
UnifiedResources as SharedUnifiedResources,
UnifiedResourceDefinition,
UnifiedResourcesPinning,
UnifiedResourcesQueryParams,
useUnifiedResourcesFetch,
} from 'shared/components/UnifiedResources';
import {
getResourceId,
openStatusInfoPanel,
} from 'shared/components/UnifiedResources/shared/StatusInfo';
import { Attempt } from 'shared/hooks/useAsync';
import { NodeSubKind } from 'shared/services';
import {
@@ -78,6 +84,7 @@ import {
} from './ActionButtons';
import { InfoGuideSidePanel } from './InfoGuideSidePanel';
import { useResourcesContext } from './resourcesContext';
import { StatusInfo } from './StatusInfo';
import { useUserPreferences } from './useUserPreferences';
export function UnifiedResources(props: {
@@ -391,9 +398,23 @@ const Resources = memo(
}),
};
const { infoGuideConfig, panelWidth } = useInfoGuide();
const { infoGuideConfig, panelWidth, setInfoGuideConfig } = useInfoGuide();
const infoGuideSidePanelOpened = infoGuideConfig != null;
function onShowStatusInfo(resource: UnifiedResourceDefinition) {
openStatusInfoPanel({
resource,
setInfoGuideConfig,
guide: (
<StatusInfo
resource={resource}
clusterUri={props.clusterUri}
key={getResourceId(resource)}
/>
),
});
}
return (
<Box
css={marginTransitionCss({
@@ -402,8 +423,7 @@ const Resources = memo(
})}
>
<SharedUnifiedResources
// TODO(kimlisa): add support later
onShowStatusInfo={() => null}
onShowStatusInfo={onShowStatusInfo}
params={props.queryParams}
setParams={props.onParamsChange}
unifiedResourcePreferencesAttempt={props.userPreferencesAttempt}
@@ -518,6 +538,10 @@ const mapToSharedResource = (
).title,
protocol: database.protocol as DbProtocol,
requiresRequest: resource.requiresRequest,
targetHealth: database.targetHealth && {
status: database.targetHealth.status as ResourceStatus,
error: database.targetHealth.error,
},
},
ui: {
ActionButton: <ConnectDatabaseActionButton database={database} />,