From 1eea7982cdf5f4213f4356cea18878523fed22f0 Mon Sep 17 00:00:00 2001 From: Andrew Mason Date: Wed, 3 Mar 2021 16:17:08 -0500 Subject: [PATCH 1/3] Add FindSchema RPC, run generators and set up stubs Signed-off-by: Andrew Mason --- go/vt/proto/vtadmin/vtadmin.pb.go | 430 ++++++++++++++++++++++++----- go/vt/vtadmin/api.go | 6 + go/vt/vtadmin/http/schemas.go | 6 + proto/vtadmin.proto | 13 + web/vtadmin/src/proto/vtadmin.d.ts | 117 ++++++++ web/vtadmin/src/proto/vtadmin.js | 259 +++++++++++++++++ 6 files changed, 760 insertions(+), 71 deletions(-) diff --git a/go/vt/proto/vtadmin/vtadmin.pb.go b/go/vt/proto/vtadmin/vtadmin.pb.go index 6e55ee65063..1c420e539b7 100644 --- a/go/vt/proto/vtadmin/vtadmin.pb.go +++ b/go/vt/proto/vtadmin/vtadmin.pb.go @@ -450,7 +450,61 @@ func (m *VTGate) GetKeyspaces() []string { return nil } -// Request/Response types +type FindSchemaRequest struct { + Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` + ClusterIds []string `protobuf:"bytes,2,rep,name=cluster_ids,json=clusterIds,proto3" json:"cluster_ids,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FindSchemaRequest) Reset() { *m = FindSchemaRequest{} } +func (m *FindSchemaRequest) String() string { return proto.CompactTextString(m) } +func (*FindSchemaRequest) ProtoMessage() {} +func (*FindSchemaRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_609739e22a0a50b3, []int{6} +} +func (m *FindSchemaRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FindSchemaRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FindSchemaRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *FindSchemaRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_FindSchemaRequest.Merge(m, src) +} +func (m *FindSchemaRequest) XXX_Size() int { + return m.Size() +} +func (m *FindSchemaRequest) XXX_DiscardUnknown() { + xxx_messageInfo_FindSchemaRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_FindSchemaRequest proto.InternalMessageInfo + +func (m *FindSchemaRequest) GetTable() string { + if m != nil { + return m.Table + } + return "" +} + +func (m *FindSchemaRequest) GetClusterIds() []string { + if m != nil { + return m.ClusterIds + } + return nil +} + type GetClustersRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -461,7 +515,7 @@ func (m *GetClustersRequest) Reset() { *m = GetClustersRequest{} } func (m *GetClustersRequest) String() string { return proto.CompactTextString(m) } func (*GetClustersRequest) ProtoMessage() {} func (*GetClustersRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{6} + return fileDescriptor_609739e22a0a50b3, []int{7} } func (m *GetClustersRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -501,7 +555,7 @@ func (m *GetClustersResponse) Reset() { *m = GetClustersResponse{} } func (m *GetClustersResponse) String() string { return proto.CompactTextString(m) } func (*GetClustersResponse) ProtoMessage() {} func (*GetClustersResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{7} + return fileDescriptor_609739e22a0a50b3, []int{8} } func (m *GetClustersResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -548,7 +602,7 @@ func (m *GetGatesRequest) Reset() { *m = GetGatesRequest{} } func (m *GetGatesRequest) String() string { return proto.CompactTextString(m) } func (*GetGatesRequest) ProtoMessage() {} func (*GetGatesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{8} + return fileDescriptor_609739e22a0a50b3, []int{9} } func (m *GetGatesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -595,7 +649,7 @@ func (m *GetGatesResponse) Reset() { *m = GetGatesResponse{} } func (m *GetGatesResponse) String() string { return proto.CompactTextString(m) } func (*GetGatesResponse) ProtoMessage() {} func (*GetGatesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{9} + return fileDescriptor_609739e22a0a50b3, []int{10} } func (m *GetGatesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -642,7 +696,7 @@ func (m *GetKeyspacesRequest) Reset() { *m = GetKeyspacesRequest{} } func (m *GetKeyspacesRequest) String() string { return proto.CompactTextString(m) } func (*GetKeyspacesRequest) ProtoMessage() {} func (*GetKeyspacesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{10} + return fileDescriptor_609739e22a0a50b3, []int{11} } func (m *GetKeyspacesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -689,7 +743,7 @@ func (m *GetKeyspacesResponse) Reset() { *m = GetKeyspacesResponse{} } func (m *GetKeyspacesResponse) String() string { return proto.CompactTextString(m) } func (*GetKeyspacesResponse) ProtoMessage() {} func (*GetKeyspacesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{11} + return fileDescriptor_609739e22a0a50b3, []int{12} } func (m *GetKeyspacesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -738,7 +792,7 @@ func (m *GetSchemaRequest) Reset() { *m = GetSchemaRequest{} } func (m *GetSchemaRequest) String() string { return proto.CompactTextString(m) } func (*GetSchemaRequest) ProtoMessage() {} func (*GetSchemaRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{12} + return fileDescriptor_609739e22a0a50b3, []int{13} } func (m *GetSchemaRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -799,7 +853,7 @@ func (m *GetSchemasRequest) Reset() { *m = GetSchemasRequest{} } func (m *GetSchemasRequest) String() string { return proto.CompactTextString(m) } func (*GetSchemasRequest) ProtoMessage() {} func (*GetSchemasRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{13} + return fileDescriptor_609739e22a0a50b3, []int{14} } func (m *GetSchemasRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -846,7 +900,7 @@ func (m *GetSchemasResponse) Reset() { *m = GetSchemasResponse{} } func (m *GetSchemasResponse) String() string { return proto.CompactTextString(m) } func (*GetSchemasResponse) ProtoMessage() {} func (*GetSchemasResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{14} + return fileDescriptor_609739e22a0a50b3, []int{15} } func (m *GetSchemasResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -897,7 +951,7 @@ func (m *GetTabletRequest) Reset() { *m = GetTabletRequest{} } func (m *GetTabletRequest) String() string { return proto.CompactTextString(m) } func (*GetTabletRequest) ProtoMessage() {} func (*GetTabletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{15} + return fileDescriptor_609739e22a0a50b3, []int{16} } func (m *GetTabletRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -951,7 +1005,7 @@ func (m *GetTabletsRequest) Reset() { *m = GetTabletsRequest{} } func (m *GetTabletsRequest) String() string { return proto.CompactTextString(m) } func (*GetTabletsRequest) ProtoMessage() {} func (*GetTabletsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{16} + return fileDescriptor_609739e22a0a50b3, []int{17} } func (m *GetTabletsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -998,7 +1052,7 @@ func (m *GetTabletsResponse) Reset() { *m = GetTabletsResponse{} } func (m *GetTabletsResponse) String() string { return proto.CompactTextString(m) } func (*GetTabletsResponse) ProtoMessage() {} func (*GetTabletsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{17} + return fileDescriptor_609739e22a0a50b3, []int{18} } func (m *GetTabletsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1047,7 +1101,7 @@ func (m *VTExplainRequest) Reset() { *m = VTExplainRequest{} } func (m *VTExplainRequest) String() string { return proto.CompactTextString(m) } func (*VTExplainRequest) ProtoMessage() {} func (*VTExplainRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{18} + return fileDescriptor_609739e22a0a50b3, []int{19} } func (m *VTExplainRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1108,7 +1162,7 @@ func (m *VTExplainResponse) Reset() { *m = VTExplainResponse{} } func (m *VTExplainResponse) String() string { return proto.CompactTextString(m) } func (*VTExplainResponse) ProtoMessage() {} func (*VTExplainResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_609739e22a0a50b3, []int{19} + return fileDescriptor_609739e22a0a50b3, []int{20} } func (m *VTExplainResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1153,6 +1207,7 @@ func init() { proto.RegisterType((*Tablet)(nil), "vtadmin.Tablet") proto.RegisterType((*Vtctld)(nil), "vtadmin.Vtctld") proto.RegisterType((*VTGate)(nil), "vtadmin.VTGate") + proto.RegisterType((*FindSchemaRequest)(nil), "vtadmin.FindSchemaRequest") proto.RegisterType((*GetClustersRequest)(nil), "vtadmin.GetClustersRequest") proto.RegisterType((*GetClustersResponse)(nil), "vtadmin.GetClustersResponse") proto.RegisterType((*GetGatesRequest)(nil), "vtadmin.GetGatesRequest") @@ -1172,63 +1227,65 @@ func init() { func init() { proto.RegisterFile("vtadmin.proto", fileDescriptor_609739e22a0a50b3) } var fileDescriptor_609739e22a0a50b3 = []byte{ - // 886 bytes of a gzipped FileDescriptorProto + // 915 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xdd, 0x6e, 0xe3, 0x44, - 0x14, 0x8e, 0x93, 0xe6, 0xc7, 0xc7, 0x4b, 0xeb, 0xce, 0x56, 0xc2, 0x78, 0xdb, 0x52, 0x8d, 0x00, - 0x05, 0x04, 0xb1, 0x14, 0x60, 0x45, 0xb9, 0x41, 0xcb, 0x6e, 0x15, 0x2d, 0x15, 0x09, 0x72, 0x42, - 0x90, 0xf6, 0xa6, 0xf2, 0xc6, 0x43, 0x6a, 0xad, 0x63, 0x67, 0x33, 0xd3, 0x88, 0xbe, 0x08, 0xe2, - 0x96, 0x87, 0xe0, 0x1d, 0xb8, 0x41, 0xe2, 0x11, 0x50, 0xb9, 0xe4, 0x25, 0x90, 0xe7, 0x2f, 0xfe, - 0xc9, 0x76, 0xdb, 0xbb, 0x99, 0xf3, 0xf7, 0x7d, 0xdf, 0x9c, 0x73, 0x9c, 0xc0, 0x3b, 0x6b, 0x16, - 0x84, 0x8b, 0x28, 0xe9, 0x2d, 0x57, 0x29, 0x4b, 0x51, 0x5b, 0x5e, 0xdd, 0x77, 0x59, 0xf0, 0x32, - 0x26, 0x6c, 0x11, 0x24, 0xc1, 0x9c, 0xac, 0xc2, 0x80, 0x05, 0x22, 0xc2, 0xdd, 0x65, 0xe9, 0x32, - 0xcd, 0xdd, 0xf7, 0xd6, 0x6c, 0xc6, 0xe2, 0x8d, 0x01, 0x7f, 0x06, 0xed, 0xa7, 0xf1, 0x15, 0x65, - 0x64, 0x85, 0x76, 0xa1, 0x1e, 0x85, 0x8e, 0x71, 0x62, 0x74, 0x4d, 0xbf, 0x1e, 0x85, 0x08, 0xc1, - 0x4e, 0x12, 0x2c, 0x88, 0x53, 0xe7, 0x16, 0x7e, 0xc6, 0xff, 0x19, 0xd0, 0x39, 0x27, 0xd7, 0x74, - 0x19, 0xcc, 0x08, 0xfa, 0x04, 0xda, 0x33, 0x91, 0xcb, 0xb3, 0xac, 0xbe, 0xdd, 0x53, 0xfc, 0x64, - 0x4d, 0x5f, 0x05, 0x20, 0x0f, 0x3a, 0xaf, 0x64, 0x1e, 0x2f, 0x68, 0xf5, 0x1f, 0xf6, 0x36, 0x5c, - 0x54, 0x49, 0x5f, 0x07, 0xa1, 0x2f, 0xa1, 0x45, 0x2f, 0x83, 0x55, 0x48, 0x9d, 0xc6, 0x49, 0xa3, - 0x6b, 0xf5, 0x8f, 0x74, 0x6d, 0x15, 0xdc, 0x1b, 0x73, 0xff, 0x59, 0xc2, 0x56, 0xd7, 0xbe, 0x0c, - 0x76, 0xcf, 0xc1, 0xca, 0x99, 0x91, 0x0d, 0x8d, 0x57, 0xe4, 0x5a, 0x8a, 0xca, 0x8e, 0xe8, 0x23, - 0x68, 0xae, 0x83, 0xf8, 0x4a, 0xb1, 0xb0, 0x73, 0x2c, 0x78, 0xa2, 0x2f, 0xdc, 0x5f, 0xd7, 0xbf, - 0x32, 0xf0, 0xef, 0x06, 0xb4, 0xc6, 0xb3, 0x4b, 0xb2, 0x08, 0xee, 0xa5, 0xd5, 0x2d, 0x69, 0x35, - 0x73, 0xb2, 0x46, 0xb0, 0xcf, 0x7b, 0x75, 0x11, 0x92, 0x9f, 0xa3, 0x24, 0x62, 0x51, 0x9a, 0x28, - 0x85, 0xb8, 0x57, 0xed, 0xe2, 0x24, 0xb3, 0x3c, 0xd3, 0xa1, 0xbe, 0xcd, 0x8a, 0x06, 0x8a, 0xff, - 0x32, 0xa0, 0xc5, 0xa3, 0xd8, 0xbd, 0x38, 0x76, 0xa1, 0x25, 0xd0, 0xf4, 0x3b, 0xe8, 0x49, 0x11, - 0xd5, 0x7c, 0xe9, 0x47, 0x7d, 0x68, 0x52, 0x16, 0x30, 0xe2, 0x34, 0x4e, 0x8c, 0xee, 0x6e, 0xff, - 0x50, 0xd7, 0x14, 0x71, 0xbd, 0x31, 0x59, 0xad, 0xa3, 0x64, 0x3e, 0xce, 0x62, 0x7c, 0x11, 0x8a, - 0x4f, 0xe1, 0x41, 0xde, 0x8c, 0x2c, 0x68, 0xff, 0x38, 0x3c, 0x1f, 0x8e, 0x7e, 0x1a, 0xda, 0xb5, - 0xec, 0x32, 0x3e, 0xf3, 0xa7, 0xcf, 0x87, 0x03, 0xdb, 0x40, 0x7b, 0x60, 0x0d, 0x47, 0x93, 0x0b, - 0x65, 0xa8, 0xe3, 0x1f, 0xa0, 0x35, 0xe5, 0x1d, 0xc9, 0x9e, 0xf1, 0x32, 0xa5, 0x8c, 0xcf, 0xa0, - 0x68, 0xa0, 0xbe, 0xe7, 0xa5, 0xd6, 0xdf, 0x22, 0x15, 0xff, 0x6a, 0x40, 0x6b, 0x3a, 0x19, 0x64, - 0x3c, 0x6e, 0x2b, 0x89, 0x60, 0x67, 0x99, 0xa6, 0xb1, 0x1a, 0xf7, 0xec, 0x9c, 0xd9, 0x66, 0x24, - 0x8e, 0xb9, 0x74, 0xd3, 0xe7, 0xe7, 0x3c, 0xf4, 0xce, 0xdb, 0x5e, 0xf9, 0x10, 0x4c, 0xd5, 0x79, - 0xea, 0x34, 0x4f, 0x1a, 0x5d, 0xd3, 0xdf, 0x18, 0xf0, 0x01, 0xa0, 0x01, 0x61, 0x32, 0x89, 0xfa, - 0xe4, 0xf5, 0x15, 0xa1, 0x0c, 0x3f, 0x85, 0x87, 0x05, 0x2b, 0x5d, 0xa6, 0x09, 0x25, 0xe8, 0x53, - 0xe8, 0xc8, 0xaa, 0xd4, 0x31, 0xf8, 0xbc, 0x54, 0x71, 0x75, 0x04, 0xee, 0xc3, 0xde, 0x80, 0xb0, - 0x4c, 0xb3, 0xaa, 0x8b, 0xde, 0x07, 0x4b, 0xba, 0x2f, 0xa2, 0x50, 0xd4, 0x30, 0x7d, 0x90, 0xa6, - 0xe7, 0x21, 0xc5, 0xa7, 0x60, 0x6f, 0x72, 0x24, 0xea, 0x87, 0xd0, 0x9c, 0x67, 0x06, 0x09, 0xb9, - 0xa7, 0x21, 0xc5, 0x83, 0xfa, 0xc2, 0x8b, 0x1f, 0x73, 0xce, 0x6a, 0x31, 0xef, 0x0e, 0x39, 0x80, - 0x83, 0x62, 0x9e, 0x84, 0xf5, 0xf2, 0xef, 0x26, 0xa0, 0xf7, 0x2b, 0xfb, 0x9f, 0x7f, 0xca, 0x19, - 0xe7, 0x2e, 0x76, 0x55, 0xa1, 0x1f, 0x01, 0x6c, 0xd0, 0x65, 0xbb, 0x4d, 0x0d, 0x7e, 0xeb, 0x96, - 0x1e, 0x40, 0x93, 0x4f, 0xbf, 0x6c, 0xbc, 0xb8, 0xe0, 0x2f, 0x60, 0x5f, 0x83, 0xdc, 0x5d, 0xe3, - 0x37, 0xbc, 0xcb, 0x3a, 0x4b, 0x2a, 0xfc, 0x18, 0xda, 0x54, 0x98, 0x2a, 0x4f, 0x2b, 0x55, 0x28, - 0x3f, 0x1e, 0x71, 0x6d, 0x72, 0x2b, 0x25, 0xea, 0x6d, 0x83, 0x5c, 0x62, 0x54, 0xaf, 0x30, 0x12, - 0x3a, 0x44, 0xc1, 0xfb, 0xea, 0xd0, 0x59, 0x1b, 0x1d, 0xe2, 0x3b, 0x51, 0xd5, 0x21, 0x19, 0x2b, - 0x3f, 0x7e, 0x01, 0xf6, 0x74, 0x72, 0xf6, 0xcb, 0x32, 0x0e, 0xa2, 0x44, 0xa1, 0x3a, 0xc5, 0x4f, - 0x96, 0x79, 0xb7, 0x8f, 0xa8, 0x0d, 0x0d, 0xfa, 0x5a, 0x6d, 0x65, 0x76, 0xc4, 0x1e, 0xec, 0xe7, - 0x6a, 0x4b, 0x6e, 0x2e, 0x74, 0x56, 0xf2, 0xac, 0x1e, 0x49, 0xdd, 0xfb, 0x7f, 0xec, 0x40, 0x7b, - 0x3a, 0x79, 0x92, 0x11, 0x45, 0xdf, 0x81, 0x95, 0xdb, 0x38, 0xf4, 0x48, 0x2b, 0xa8, 0x6e, 0xa7, - 0x7b, 0xb8, 0xdd, 0x29, 0xaa, 0xe2, 0x1a, 0x7a, 0x02, 0x1d, 0xb5, 0x44, 0xc8, 0xc9, 0xc7, 0xe6, - 0x77, 0xd1, 0x7d, 0x6f, 0x8b, 0x47, 0x97, 0xf8, 0x1e, 0x1e, 0xe4, 0x97, 0x02, 0x15, 0x20, 0xcb, - 0x3b, 0xe6, 0x1e, 0xbd, 0xc1, 0xab, 0xcb, 0x9d, 0x82, 0xa9, 0xe7, 0x0f, 0x15, 0x80, 0x0b, 0xeb, - 0xe2, 0x96, 0x07, 0x10, 0xd7, 0xd0, 0x00, 0x60, 0x33, 0xba, 0xc8, 0xad, 0xe6, 0x6a, 0x16, 0x8f, - 0xb6, 0xfa, 0x4a, 0x1c, 0xe4, 0xcf, 0x54, 0x81, 0x43, 0x61, 0xac, 0xdd, 0xf2, 0xf0, 0x68, 0x0e, - 0x72, 0xec, 0x8a, 0x1c, 0x8a, 0x13, 0x5c, 0xe4, 0x50, 0x9a, 0x53, 0x5c, 0x43, 0xcf, 0xc0, 0xd4, - 0x23, 0x92, 0xe3, 0x50, 0x1e, 0x49, 0xd7, 0xdd, 0xe6, 0x52, 0x55, 0xbe, 0x7d, 0xfc, 0xe7, 0xcd, - 0xb1, 0xf1, 0xf7, 0xcd, 0xb1, 0xf1, 0xcf, 0xcd, 0xb1, 0xf1, 0xdb, 0xbf, 0xc7, 0xb5, 0x17, 0x1f, - 0xac, 0x23, 0x46, 0x28, 0xed, 0x45, 0xa9, 0x27, 0x4e, 0xde, 0x3c, 0xf5, 0xd6, 0xcc, 0xe3, 0xff, - 0xaf, 0x3c, 0x59, 0xeb, 0x65, 0x8b, 0x5f, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x9e, - 0x12, 0x81, 0xc2, 0x09, 0x00, 0x00, + 0x14, 0x8e, 0x93, 0xe6, 0xc7, 0x27, 0x4b, 0xeb, 0xcc, 0x56, 0xc2, 0x78, 0xdb, 0x52, 0x8d, 0x00, + 0x05, 0x04, 0x89, 0x14, 0x60, 0x45, 0xe1, 0x02, 0x2d, 0xbb, 0x25, 0xda, 0xad, 0x48, 0x91, 0x13, + 0x82, 0xb4, 0x37, 0x95, 0x37, 0x1e, 0x5a, 0x6b, 0x5d, 0x3b, 0x9b, 0x99, 0x46, 0xf4, 0x45, 0x10, + 0xb7, 0xbc, 0x0d, 0x37, 0x48, 0x3c, 0x02, 0x2a, 0x97, 0xdc, 0xf1, 0x04, 0xc8, 0xf3, 0xe7, 0xb1, + 0x5d, 0xfa, 0x73, 0x37, 0x73, 0xce, 0x99, 0xef, 0x7c, 0xdf, 0xf9, 0x71, 0x02, 0x6f, 0xad, 0x59, + 0x10, 0x9e, 0x47, 0xc9, 0x60, 0xb9, 0x4a, 0x59, 0x8a, 0xda, 0xf2, 0xea, 0xbd, 0xcd, 0x82, 0x57, + 0x31, 0x61, 0xe7, 0x41, 0x12, 0x9c, 0x92, 0x55, 0x18, 0xb0, 0x40, 0x44, 0x78, 0x9b, 0x2c, 0x5d, + 0xa6, 0xc6, 0x7d, 0x6b, 0xcd, 0x16, 0x2c, 0xce, 0x0d, 0xf8, 0x13, 0x68, 0x3f, 0x8d, 0x2f, 0x28, + 0x23, 0x2b, 0xb4, 0x09, 0xf5, 0x28, 0x74, 0xad, 0x7d, 0xab, 0x6f, 0xfb, 0xf5, 0x28, 0x44, 0x08, + 0x36, 0x92, 0xe0, 0x9c, 0xb8, 0x75, 0x6e, 0xe1, 0x67, 0xfc, 0x8f, 0x05, 0x9d, 0x23, 0x72, 0x49, + 0x97, 0xc1, 0x82, 0xa0, 0x8f, 0xa0, 0xbd, 0x10, 0x6f, 0xf9, 0xab, 0xee, 0xc8, 0x19, 0x28, 0x7e, + 0x12, 0xd3, 0x57, 0x01, 0x68, 0x08, 0x9d, 0xd7, 0xf2, 0x1d, 0x07, 0xec, 0x8e, 0x1e, 0x0e, 0x72, + 0x2e, 0x0a, 0xd2, 0xd7, 0x41, 0xe8, 0x73, 0x68, 0xd1, 0xb3, 0x60, 0x15, 0x52, 0xb7, 0xb1, 0xdf, + 0xe8, 0x77, 0x47, 0xbb, 0x1a, 0x5b, 0x05, 0x0f, 0xa6, 0xdc, 0x7f, 0x98, 0xb0, 0xd5, 0xa5, 0x2f, + 0x83, 0xbd, 0x23, 0xe8, 0x1a, 0x66, 0xe4, 0x40, 0xe3, 0x35, 0xb9, 0x94, 0xa2, 0xb2, 0x23, 0xfa, + 0x00, 0x9a, 0xeb, 0x20, 0xbe, 0x50, 0x2c, 0x1c, 0x83, 0x05, 0x7f, 0xe8, 0x0b, 0xf7, 0x97, 0xf5, + 0x2f, 0x2c, 0xfc, 0x9b, 0x05, 0xad, 0xe9, 0xe2, 0x8c, 0x9c, 0x07, 0xf7, 0xd2, 0xea, 0x95, 0xb4, + 0xda, 0x86, 0xac, 0x63, 0xe8, 0xf1, 0x5e, 0x9d, 0x84, 0xe4, 0xa7, 0x28, 0x89, 0x58, 0x94, 0x26, + 0x4a, 0x21, 0x1e, 0x54, 0xbb, 0x38, 0xcb, 0x2c, 0xcf, 0x74, 0xa8, 0xef, 0xb0, 0xa2, 0x81, 0xe2, + 0x3f, 0x2c, 0x68, 0xf1, 0x28, 0x76, 0x2f, 0x8e, 0x7d, 0x68, 0x89, 0x6c, 0xba, 0x0e, 0x7a, 0x52, + 0x04, 0x9a, 0x2f, 0xfd, 0x68, 0x04, 0x4d, 0xca, 0x02, 0x46, 0xdc, 0xc6, 0xbe, 0xd5, 0xdf, 0x1c, + 0xed, 0x68, 0x4c, 0x11, 0x37, 0x98, 0x92, 0xd5, 0x3a, 0x4a, 0x4e, 0xa7, 0x59, 0x8c, 0x2f, 0x42, + 0xf1, 0x01, 0x3c, 0x30, 0xcd, 0xa8, 0x0b, 0xed, 0x1f, 0x26, 0x47, 0x93, 0xe3, 0x1f, 0x27, 0x4e, + 0x2d, 0xbb, 0x4c, 0x0f, 0xfd, 0xf9, 0xf3, 0xc9, 0xd8, 0xb1, 0xd0, 0x16, 0x74, 0x27, 0xc7, 0xb3, + 0x13, 0x65, 0xa8, 0xe3, 0xef, 0xa1, 0x35, 0xe7, 0x1d, 0xc9, 0xca, 0x78, 0x96, 0x52, 0xc6, 0x67, + 0x50, 0x34, 0x50, 0xdf, 0x4d, 0xa9, 0xf5, 0x5b, 0xa4, 0xe2, 0x5f, 0x2c, 0x68, 0xcd, 0x67, 0xe3, + 0x8c, 0xc7, 0x4d, 0x90, 0x08, 0x36, 0x96, 0x69, 0x1a, 0xab, 0x71, 0xcf, 0xce, 0x99, 0x6d, 0x41, + 0xe2, 0x98, 0x4b, 0xb7, 0x7d, 0x7e, 0x36, 0x53, 0x6f, 0xdc, 0x56, 0xe5, 0x1d, 0xb0, 0x55, 0xe7, + 0xa9, 0xdb, 0xdc, 0x6f, 0xf4, 0x6d, 0x3f, 0x37, 0xe0, 0x17, 0xd0, 0xfb, 0x36, 0x4a, 0x42, 0x31, + 0x61, 0x3e, 0x79, 0x73, 0x41, 0x28, 0x43, 0xdb, 0xd0, 0xe4, 0x85, 0x97, 0xfc, 0xc4, 0x05, 0xbd, + 0x0b, 0x5d, 0x89, 0x79, 0x12, 0x85, 0xd4, 0xad, 0x73, 0x28, 0x90, 0xa6, 0xe7, 0x21, 0xc5, 0xdb, + 0x80, 0xc6, 0x84, 0x49, 0x02, 0x54, 0x82, 0xe1, 0xa7, 0xf0, 0xb0, 0x60, 0xa5, 0xcb, 0x34, 0xa1, + 0x04, 0x7d, 0x0c, 0x1d, 0xf9, 0x94, 0xba, 0x16, 0x9f, 0xbd, 0xaa, 0x06, 0x1d, 0x81, 0x47, 0xb0, + 0x35, 0x26, 0x2c, 0xab, 0x9f, 0xc2, 0x2d, 0xd3, 0xb1, 0x2a, 0x74, 0x0e, 0xc0, 0xc9, 0xdf, 0xc8, + 0xac, 0xef, 0x43, 0xf3, 0x34, 0x33, 0xc8, 0x94, 0x5b, 0x3a, 0xa5, 0x68, 0x8e, 0x2f, 0xbc, 0xf8, + 0x31, 0xe7, 0xac, 0x96, 0xfc, 0xee, 0x29, 0xc7, 0xb0, 0x5d, 0x7c, 0x27, 0xd3, 0x0e, 0xcd, 0x1e, + 0x88, 0xd4, 0xbd, 0xca, 0xb7, 0xc4, 0x6c, 0xcb, 0x82, 0x73, 0x2f, 0x76, 0x65, 0x17, 0x20, 0xcf, + 0x2e, 0x5b, 0x63, 0xeb, 0xe4, 0x37, 0x6e, 0xbc, 0x6e, 0x68, 0xc3, 0x68, 0x28, 0xfe, 0x0c, 0x7a, + 0x3a, 0xc9, 0xdd, 0x35, 0x7e, 0xcd, 0xbb, 0xac, 0x5f, 0x49, 0x85, 0x1f, 0x42, 0x9b, 0x0a, 0x53, + 0xa5, 0xb4, 0x52, 0x85, 0xf2, 0xe3, 0x63, 0xae, 0x4d, 0x6e, 0xb8, 0xcc, 0x7a, 0xd3, 0x52, 0xdc, + 0x3a, 0x77, 0x42, 0x87, 0x00, 0xbc, 0xaf, 0x0e, 0xfd, 0x2a, 0xd7, 0x21, 0xbe, 0x39, 0x55, 0x1d, + 0x92, 0xb1, 0xf2, 0xe3, 0x97, 0xe0, 0xcc, 0x67, 0x87, 0x3f, 0x2f, 0xe3, 0x20, 0x4a, 0x54, 0x56, + 0xb7, 0xf8, 0xf9, 0xb3, 0xef, 0xf6, 0x41, 0x76, 0xa0, 0x41, 0xdf, 0xa8, 0x0d, 0xcf, 0x8e, 0x78, + 0x08, 0x3d, 0x03, 0x5b, 0x72, 0xf3, 0xa0, 0xb3, 0x92, 0x67, 0x55, 0x24, 0x75, 0x1f, 0xfd, 0xbb, + 0x01, 0xed, 0xf9, 0xec, 0x49, 0x46, 0x14, 0x7d, 0x05, 0x90, 0xef, 0x34, 0xf2, 0xb4, 0x80, 0xca, + 0xa2, 0x7b, 0xe5, 0x26, 0xe1, 0x1a, 0x7a, 0x01, 0x5d, 0x63, 0x5d, 0xd1, 0x23, 0x1d, 0x51, 0x5d, + 0x6d, 0x6f, 0xe7, 0x7a, 0xa7, 0xa0, 0x84, 0x6b, 0xe8, 0x09, 0x74, 0xd4, 0x06, 0x22, 0xd7, 0x8c, + 0x35, 0x17, 0xd9, 0x7b, 0xe7, 0x1a, 0x8f, 0x86, 0xf8, 0x0e, 0x1e, 0x98, 0x1b, 0x85, 0x0a, 0x29, + 0xcb, 0x0b, 0xea, 0xed, 0xfe, 0x8f, 0x57, 0xc3, 0x1d, 0x80, 0xad, 0x87, 0x17, 0x15, 0x12, 0xdf, + 0x5a, 0x98, 0x31, 0x40, 0x3e, 0xf7, 0x46, 0x55, 0x2b, 0x2b, 0xe4, 0x3d, 0xba, 0xd6, 0x57, 0xe2, + 0x20, 0x7f, 0x2f, 0x0b, 0x1c, 0x0a, 0x3b, 0xe1, 0x95, 0x27, 0x4f, 0x73, 0x90, 0x33, 0x5b, 0xe4, + 0x50, 0x1c, 0xff, 0x22, 0x87, 0xd2, 0x90, 0xe3, 0x1a, 0x7a, 0x06, 0xb6, 0x9e, 0x2f, 0x83, 0x43, + 0x79, 0x9e, 0x3d, 0xef, 0x3a, 0x97, 0x42, 0xf9, 0xe6, 0xf1, 0xef, 0x57, 0x7b, 0xd6, 0x9f, 0x57, + 0x7b, 0xd6, 0x5f, 0x57, 0x7b, 0xd6, 0xaf, 0x7f, 0xef, 0xd5, 0x5e, 0xbe, 0xb7, 0x8e, 0x18, 0xa1, + 0x74, 0x10, 0xa5, 0x43, 0x71, 0x1a, 0x9e, 0xa6, 0xc3, 0x35, 0x1b, 0xf2, 0x3f, 0x7a, 0x43, 0x89, + 0xf5, 0xaa, 0xc5, 0xaf, 0x9f, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0xde, 0x92, 0xaf, 0x3f, 0x4b, + 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1243,6 +1300,13 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type VTAdminClient interface { + // FindSchema returns a single Schema that matches the provided table name + // across all specified clusters IDs. Not specifying a set of cluster IDs + // causes the search to span all configured clusters. + // + // An error occurs if either no table exists across any of the clusters with + // the specified table name, or if multiple tables exist with that name. + FindSchema(ctx context.Context, in *FindSchemaRequest, opts ...grpc.CallOption) (*Schema, error) // GetClusters returns all configured clusters. GetClusters(ctx context.Context, in *GetClustersRequest, opts ...grpc.CallOption) (*GetClustersResponse, error) // GetGates returns all gates across all the specified clusters. @@ -1271,6 +1335,15 @@ func NewVTAdminClient(cc *grpc.ClientConn) VTAdminClient { return &vTAdminClient{cc} } +func (c *vTAdminClient) FindSchema(ctx context.Context, in *FindSchemaRequest, opts ...grpc.CallOption) (*Schema, error) { + out := new(Schema) + err := c.cc.Invoke(ctx, "/vtadmin.VTAdmin/FindSchema", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *vTAdminClient) GetClusters(ctx context.Context, in *GetClustersRequest, opts ...grpc.CallOption) (*GetClustersResponse, error) { out := new(GetClustersResponse) err := c.cc.Invoke(ctx, "/vtadmin.VTAdmin/GetClusters", in, out, opts...) @@ -1345,6 +1418,13 @@ func (c *vTAdminClient) VTExplain(ctx context.Context, in *VTExplainRequest, opt // VTAdminServer is the server API for VTAdmin service. type VTAdminServer interface { + // FindSchema returns a single Schema that matches the provided table name + // across all specified clusters IDs. Not specifying a set of cluster IDs + // causes the search to span all configured clusters. + // + // An error occurs if either no table exists across any of the clusters with + // the specified table name, or if multiple tables exist with that name. + FindSchema(context.Context, *FindSchemaRequest) (*Schema, error) // GetClusters returns all configured clusters. GetClusters(context.Context, *GetClustersRequest) (*GetClustersResponse, error) // GetGates returns all gates across all the specified clusters. @@ -1369,6 +1449,9 @@ type VTAdminServer interface { type UnimplementedVTAdminServer struct { } +func (*UnimplementedVTAdminServer) FindSchema(ctx context.Context, req *FindSchemaRequest) (*Schema, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindSchema not implemented") +} func (*UnimplementedVTAdminServer) GetClusters(ctx context.Context, req *GetClustersRequest) (*GetClustersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetClusters not implemented") } @@ -1398,6 +1481,24 @@ func RegisterVTAdminServer(s *grpc.Server, srv VTAdminServer) { s.RegisterService(&_VTAdmin_serviceDesc, srv) } +func _VTAdmin_FindSchema_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindSchemaRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VTAdminServer).FindSchema(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtadmin.VTAdmin/FindSchema", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VTAdminServer).FindSchema(ctx, req.(*FindSchemaRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _VTAdmin_GetClusters_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetClustersRequest) if err := dec(in); err != nil { @@ -1546,6 +1647,10 @@ var _VTAdmin_serviceDesc = grpc.ServiceDesc{ ServiceName: "vtadmin.VTAdmin", HandlerType: (*VTAdminServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "FindSchema", + Handler: _VTAdmin_FindSchema_Handler, + }, { MethodName: "GetClusters", Handler: _VTAdmin_GetClusters_Handler, @@ -1932,6 +2037,49 @@ func (m *VTGate) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *FindSchemaRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FindSchemaRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FindSchemaRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.ClusterIds) > 0 { + for iNdEx := len(m.ClusterIds) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ClusterIds[iNdEx]) + copy(dAtA[i:], m.ClusterIds[iNdEx]) + i = encodeVarintVtadmin(dAtA, i, uint64(len(m.ClusterIds[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Table) > 0 { + i -= len(m.Table) + copy(dAtA[i:], m.Table) + i = encodeVarintVtadmin(dAtA, i, uint64(len(m.Table))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *GetClustersRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2648,6 +2796,28 @@ func (m *VTGate) Size() (n int) { return n } +func (m *FindSchemaRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Table) + if l > 0 { + n += 1 + l + sovVtadmin(uint64(l)) + } + if len(m.ClusterIds) > 0 { + for _, s := range m.ClusterIds { + l = len(s) + n += 1 + l + sovVtadmin(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func (m *GetClustersRequest) Size() (n int) { if m == nil { return 0 @@ -3928,6 +4098,124 @@ func (m *VTGate) Unmarshal(dAtA []byte) error { } return nil } +func (m *FindSchemaRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVtadmin + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FindSchemaRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FindSchemaRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Table", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVtadmin + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthVtadmin + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthVtadmin + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Table = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClusterIds", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVtadmin + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthVtadmin + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthVtadmin + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClusterIds = append(m.ClusterIds, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipVtadmin(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthVtadmin + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthVtadmin + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *GetClustersRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/go/vt/vtadmin/api.go b/go/vt/vtadmin/api.go index a3387aa6a4e..1932fec1a3b 100644 --- a/go/vt/vtadmin/api.go +++ b/go/vt/vtadmin/api.go @@ -88,6 +88,7 @@ func NewAPI(clusters []*cluster.Cluster, opts grpcserver.Options, httpOpts vtadm router.HandleFunc("/clusters", httpAPI.Adapt(vtadminhttp.GetClusters)).Name("API.GetClusters") router.HandleFunc("/gates", httpAPI.Adapt(vtadminhttp.GetGates)).Name("API.GetGates") router.HandleFunc("/keyspaces", httpAPI.Adapt(vtadminhttp.GetKeyspaces)).Name("API.GetKeyspaces") + router.HandleFunc("/schema/{table}", httpAPI.Adapt(vtadminhttp.FindSchema)).Name("API.FindSchema") router.HandleFunc("/schema/{cluster_id}/{keyspace}/{table}", httpAPI.Adapt(vtadminhttp.GetSchema)).Name("API.GetSchema") router.HandleFunc("/schemas", httpAPI.Adapt(vtadminhttp.GetSchemas)).Name("API.GetSchemas") router.HandleFunc("/tablets", httpAPI.Adapt(vtadminhttp.GetTablets)).Name("API.GetTablets") @@ -125,6 +126,11 @@ func (api *API) ListenAndServe() error { return api.serv.ListenAndServe() } +// FindSchema is part of the vtadminpb.VTAdminServer interface. +func (api *API) FindSchema(ctx context.Context, req *vtadminpb.FindSchemaRequest) (*vtadminpb.Schema, error) { + panic("unimplemented!") +} + // GetClusters is part of the vtadminpb.VTAdminServer interface. func (api *API) GetClusters(ctx context.Context, req *vtadminpb.GetClustersRequest) (*vtadminpb.GetClustersResponse, error) { span, _ := trace.NewSpan(ctx, "API.GetClusters") diff --git a/go/vt/vtadmin/http/schemas.go b/go/vt/vtadmin/http/schemas.go index e00fa7339e0..8fdcb92c9c2 100644 --- a/go/vt/vtadmin/http/schemas.go +++ b/go/vt/vtadmin/http/schemas.go @@ -22,6 +22,12 @@ import ( vtadminpb "vitess.io/vitess/go/vt/proto/vtadmin" ) +// FindSchema implements the http wrapper for the +// /schema/{table}[?cluster=[&cluster=]] route. +func FindSchema(ctx context.Context, r Request, api *API) *JSONResponse { + panic("unimplemented!") +} + // GetSchema implements the http wrapper for the // /schema/{cluster_id}/{keyspace}/{table} route. func GetSchema(ctx context.Context, r Request, api *API) *JSONResponse { diff --git a/proto/vtadmin.proto b/proto/vtadmin.proto index 446ef8c38bc..374481b82fc 100644 --- a/proto/vtadmin.proto +++ b/proto/vtadmin.proto @@ -30,6 +30,13 @@ import "vtctldata.proto"; // VTAdmin is the Vitess Admin API service. It provides RPCs that operate on // across a range of Vitess clusters. service VTAdmin { + // FindSchema returns a single Schema that matches the provided table name + // across all specified clusters IDs. Not specifying a set of cluster IDs + // causes the search to span all configured clusters. + // + // An error occurs if either no table exists across any of the clusters with + // the specified table name, or if multiple tables exist with that name. + rpc FindSchema(FindSchemaRequest) returns (Schema) {}; // GetClusters returns all configured clusters. rpc GetClusters(GetClustersRequest) returns (GetClustersResponse) {}; // GetGates returns all gates across all the specified clusters. @@ -111,6 +118,12 @@ message VTGate { } /* Request/Response types */ + +message FindSchemaRequest { + string table = 1; + repeated string cluster_ids = 2; +} + message GetClustersRequest {} message GetClustersResponse { diff --git a/web/vtadmin/src/proto/vtadmin.d.ts b/web/vtadmin/src/proto/vtadmin.d.ts index 6818c22a451..fe68a042845 100644 --- a/web/vtadmin/src/proto/vtadmin.d.ts +++ b/web/vtadmin/src/proto/vtadmin.d.ts @@ -22,6 +22,20 @@ export namespace vtadmin { */ public static create(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): VTAdmin; + /** + * Calls FindSchema. + * @param request FindSchemaRequest message or plain object + * @param callback Node-style callback called with the error, if any, and Schema + */ + public findSchema(request: vtadmin.IFindSchemaRequest, callback: vtadmin.VTAdmin.FindSchemaCallback): void; + + /** + * Calls FindSchema. + * @param request FindSchemaRequest message or plain object + * @returns Promise + */ + public findSchema(request: vtadmin.IFindSchemaRequest): Promise; + /** * Calls GetClusters. * @param request GetClustersRequest message or plain object @@ -137,6 +151,13 @@ export namespace vtadmin { namespace VTAdmin { + /** + * Callback as used by {@link vtadmin.VTAdmin#findSchema}. + * @param error Error, if any + * @param [response] Schema + */ + type FindSchemaCallback = (error: (Error|null), response?: vtadmin.Schema) => void; + /** * Callback as used by {@link vtadmin.VTAdmin#getClusters}. * @param error Error, if any @@ -816,6 +837,102 @@ export namespace vtadmin { public toJSON(): { [k: string]: any }; } + /** Properties of a FindSchemaRequest. */ + interface IFindSchemaRequest { + + /** FindSchemaRequest table */ + table?: (string|null); + + /** FindSchemaRequest cluster_ids */ + cluster_ids?: (string[]|null); + } + + /** Represents a FindSchemaRequest. */ + class FindSchemaRequest implements IFindSchemaRequest { + + /** + * Constructs a new FindSchemaRequest. + * @param [properties] Properties to set + */ + constructor(properties?: vtadmin.IFindSchemaRequest); + + /** FindSchemaRequest table. */ + public table: string; + + /** FindSchemaRequest cluster_ids. */ + public cluster_ids: string[]; + + /** + * Creates a new FindSchemaRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns FindSchemaRequest instance + */ + public static create(properties?: vtadmin.IFindSchemaRequest): vtadmin.FindSchemaRequest; + + /** + * Encodes the specified FindSchemaRequest message. Does not implicitly {@link vtadmin.FindSchemaRequest.verify|verify} messages. + * @param message FindSchemaRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtadmin.IFindSchemaRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified FindSchemaRequest message, length delimited. Does not implicitly {@link vtadmin.FindSchemaRequest.verify|verify} messages. + * @param message FindSchemaRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtadmin.IFindSchemaRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a FindSchemaRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns FindSchemaRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtadmin.FindSchemaRequest; + + /** + * Decodes a FindSchemaRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns FindSchemaRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtadmin.FindSchemaRequest; + + /** + * Verifies a FindSchemaRequest message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a FindSchemaRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns FindSchemaRequest + */ + public static fromObject(object: { [k: string]: any }): vtadmin.FindSchemaRequest; + + /** + * Creates a plain object from a FindSchemaRequest message. Also converts values to other types if specified. + * @param message FindSchemaRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtadmin.FindSchemaRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this FindSchemaRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + } + /** Properties of a GetClustersRequest. */ interface IGetClustersRequest { } diff --git a/web/vtadmin/src/proto/vtadmin.js b/web/vtadmin/src/proto/vtadmin.js index 95e16348a97..2b81fea9b98 100644 --- a/web/vtadmin/src/proto/vtadmin.js +++ b/web/vtadmin/src/proto/vtadmin.js @@ -50,6 +50,39 @@ $root.vtadmin = (function() { return new this(rpcImpl, requestDelimited, responseDelimited); }; + /** + * Callback as used by {@link vtadmin.VTAdmin#findSchema}. + * @memberof vtadmin.VTAdmin + * @typedef FindSchemaCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {vtadmin.Schema} [response] Schema + */ + + /** + * Calls FindSchema. + * @function findSchema + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IFindSchemaRequest} request FindSchemaRequest message or plain object + * @param {vtadmin.VTAdmin.FindSchemaCallback} callback Node-style callback called with the error, if any, and Schema + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(VTAdmin.prototype.findSchema = function findSchema(request, callback) { + return this.rpcCall(findSchema, $root.vtadmin.FindSchemaRequest, $root.vtadmin.Schema, request, callback); + }, "name", { value: "FindSchema" }); + + /** + * Calls FindSchema. + * @function findSchema + * @memberof vtadmin.VTAdmin + * @instance + * @param {vtadmin.IFindSchemaRequest} request FindSchemaRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link vtadmin.VTAdmin#getClusters}. * @memberof vtadmin.VTAdmin @@ -1860,6 +1893,232 @@ $root.vtadmin = (function() { return VTGate; })(); + vtadmin.FindSchemaRequest = (function() { + + /** + * Properties of a FindSchemaRequest. + * @memberof vtadmin + * @interface IFindSchemaRequest + * @property {string|null} [table] FindSchemaRequest table + * @property {Array.|null} [cluster_ids] FindSchemaRequest cluster_ids + */ + + /** + * Constructs a new FindSchemaRequest. + * @memberof vtadmin + * @classdesc Represents a FindSchemaRequest. + * @implements IFindSchemaRequest + * @constructor + * @param {vtadmin.IFindSchemaRequest=} [properties] Properties to set + */ + function FindSchemaRequest(properties) { + this.cluster_ids = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * FindSchemaRequest table. + * @member {string} table + * @memberof vtadmin.FindSchemaRequest + * @instance + */ + FindSchemaRequest.prototype.table = ""; + + /** + * FindSchemaRequest cluster_ids. + * @member {Array.} cluster_ids + * @memberof vtadmin.FindSchemaRequest + * @instance + */ + FindSchemaRequest.prototype.cluster_ids = $util.emptyArray; + + /** + * Creates a new FindSchemaRequest instance using the specified properties. + * @function create + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {vtadmin.IFindSchemaRequest=} [properties] Properties to set + * @returns {vtadmin.FindSchemaRequest} FindSchemaRequest instance + */ + FindSchemaRequest.create = function create(properties) { + return new FindSchemaRequest(properties); + }; + + /** + * Encodes the specified FindSchemaRequest message. Does not implicitly {@link vtadmin.FindSchemaRequest.verify|verify} messages. + * @function encode + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {vtadmin.IFindSchemaRequest} message FindSchemaRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + FindSchemaRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.table != null && Object.hasOwnProperty.call(message, "table")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.table); + if (message.cluster_ids != null && message.cluster_ids.length) + for (var i = 0; i < message.cluster_ids.length; ++i) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.cluster_ids[i]); + return writer; + }; + + /** + * Encodes the specified FindSchemaRequest message, length delimited. Does not implicitly {@link vtadmin.FindSchemaRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {vtadmin.IFindSchemaRequest} message FindSchemaRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + FindSchemaRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a FindSchemaRequest message from the specified reader or buffer. + * @function decode + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtadmin.FindSchemaRequest} FindSchemaRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + FindSchemaRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtadmin.FindSchemaRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.table = reader.string(); + break; + case 2: + if (!(message.cluster_ids && message.cluster_ids.length)) + message.cluster_ids = []; + message.cluster_ids.push(reader.string()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a FindSchemaRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtadmin.FindSchemaRequest} FindSchemaRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + FindSchemaRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a FindSchemaRequest message. + * @function verify + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + FindSchemaRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.table != null && message.hasOwnProperty("table")) + if (!$util.isString(message.table)) + return "table: string expected"; + if (message.cluster_ids != null && message.hasOwnProperty("cluster_ids")) { + if (!Array.isArray(message.cluster_ids)) + return "cluster_ids: array expected"; + for (var i = 0; i < message.cluster_ids.length; ++i) + if (!$util.isString(message.cluster_ids[i])) + return "cluster_ids: string[] expected"; + } + return null; + }; + + /** + * Creates a FindSchemaRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {Object.} object Plain object + * @returns {vtadmin.FindSchemaRequest} FindSchemaRequest + */ + FindSchemaRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtadmin.FindSchemaRequest) + return object; + var message = new $root.vtadmin.FindSchemaRequest(); + if (object.table != null) + message.table = String(object.table); + if (object.cluster_ids) { + if (!Array.isArray(object.cluster_ids)) + throw TypeError(".vtadmin.FindSchemaRequest.cluster_ids: array expected"); + message.cluster_ids = []; + for (var i = 0; i < object.cluster_ids.length; ++i) + message.cluster_ids[i] = String(object.cluster_ids[i]); + } + return message; + }; + + /** + * Creates a plain object from a FindSchemaRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtadmin.FindSchemaRequest + * @static + * @param {vtadmin.FindSchemaRequest} message FindSchemaRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + FindSchemaRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.cluster_ids = []; + if (options.defaults) + object.table = ""; + if (message.table != null && message.hasOwnProperty("table")) + object.table = message.table; + if (message.cluster_ids && message.cluster_ids.length) { + object.cluster_ids = []; + for (var j = 0; j < message.cluster_ids.length; ++j) + object.cluster_ids[j] = message.cluster_ids[j]; + } + return object; + }; + + /** + * Converts this FindSchemaRequest to JSON. + * @function toJSON + * @memberof vtadmin.FindSchemaRequest + * @instance + * @returns {Object.} JSON object + */ + FindSchemaRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return FindSchemaRequest; + })(); + vtadmin.GetClustersRequest = (function() { /** From 210458e0e8bc8eb6a8bcf71f113aa0f61d49070e Mon Sep 17 00:00:00 2001 From: Andrew Mason Date: Wed, 3 Mar 2021 20:45:39 -0500 Subject: [PATCH 2/3] Implement `FindSchema` method and http wrapper Signed-off-by: Andrew Mason --- go/vt/vtadmin/api.go | 73 +++++++++++++++++++++++++++++++++- go/vt/vtadmin/errors/errors.go | 10 ++++- go/vt/vtadmin/http/schemas.go | 10 ++++- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/go/vt/vtadmin/api.go b/go/vt/vtadmin/api.go index 1932fec1a3b..d6ad2ab3cee 100644 --- a/go/vt/vtadmin/api.go +++ b/go/vt/vtadmin/api.go @@ -29,6 +29,7 @@ import ( "vitess.io/vitess/go/trace" "vitess.io/vitess/go/vt/concurrency" + "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/vtadmin/cluster" @@ -128,7 +129,77 @@ func (api *API) ListenAndServe() error { // FindSchema is part of the vtadminpb.VTAdminServer interface. func (api *API) FindSchema(ctx context.Context, req *vtadminpb.FindSchemaRequest) (*vtadminpb.Schema, error) { - panic("unimplemented!") + span, _ := trace.NewSpan(ctx, "API.FindSchema") + defer span.Finish() + + span.Annotate("table", req.Table) + + clusters, _ := api.getClustersForRequest(req.ClusterIds) + + var ( + m sync.Mutex + wg sync.WaitGroup + rec concurrency.AllErrorRecorder + results []*vtadminpb.Schema + ) + + for _, c := range clusters { + wg.Add(1) + + go func(c *cluster.Cluster) { + defer wg.Done() + + tablets, err := c.FindTablets(ctx, func(t *vtadminpb.Tablet) bool { + // Filter out all the non-serving tablets once, to make the + // later, per-keyspace filtering slightly faster (fewer + // potentially-redundant iterations). + return t.State == vtadminpb.Tablet_SERVING + }, -1) + if err != nil { + err := fmt.Errorf("could not find any serving tablets for cluster %s: %w", c.ID, err) + rec.RecordError(err) + + return + } + + schemas, err := api.getSchemas(ctx, c, tablets) + if err != nil { + err := fmt.Errorf("%w: while collecting schemas for cluster %s", err, c.ID) + rec.RecordError(err) + + return + } + + for _, schema := range schemas { + for _, td := range schema.TableDefinitions { + if td.Name == req.Table { + m.Lock() + results = append(results, schema) + m.Unlock() + + return + } + } + } + + log.Infof("cluster %s has no tables named %s", c.ID, req.Table) + }(c) + } + + wg.Wait() + + if rec.HasErrors() { + return nil, rec.Error() + } + + switch len(results) { + case 0: + return nil, fmt.Errorf("%w: no schemas found with table named %s", errors.ErrNoSchema, req.Table) + case 1: + return results[0], nil + default: + return nil, fmt.Errorf("%w: %d schemas found with table named %s", errors.ErrAmbiguousSchema, len(results), req.Table) + } } // GetClusters is part of the vtadminpb.VTAdminServer interface. diff --git a/go/vt/vtadmin/errors/errors.go b/go/vt/vtadmin/errors/errors.go index c63f9cc78e8..a896554e685 100644 --- a/go/vt/vtadmin/errors/errors.go +++ b/go/vt/vtadmin/errors/errors.go @@ -19,17 +19,23 @@ package errors import "errors" var ( + // ErrAmbiguousSchema occurs when more than one schema is found for a given + // set of filter criteria. + ErrAmbiguousSchema = errors.New("multiple schemas found") // ErrAmbiguousTablet occurs when more than one tablet is found for a given // set of filter criteria. ErrAmbiguousTablet = errors.New("multiple tablets found") // ErrInvalidRequest occurs when a request is invalid for any reason. // For example, if mandatory parameters are undefined. ErrInvalidRequest = errors.New("Invalid request") + // ErrNoSchema occurs when a schema definition cannot be found for a given + // set of filter criteria. + ErrNoSchema = errors.New("no such schema") + // ErrNoSrvVSchema occurs when no SrvVSchema is found for a given keyspace. + ErrNoSrvVSchema = errors.New("SrvVSchema not found") // ErrNoTablet occurs when a tablet cannot be found for a given set of // filter criteria. ErrNoTablet = errors.New("no such tablet") // ErrUnsupportedCluster occurs when a cluster parameter is invalid. ErrUnsupportedCluster = errors.New("unsupported cluster(s)") - // ErrNoSrvVSchema occurs when no SrvVSchema is found for a given keyspace. - ErrNoSrvVSchema = errors.New("SrvVSchema not found") ) diff --git a/go/vt/vtadmin/http/schemas.go b/go/vt/vtadmin/http/schemas.go index 8fdcb92c9c2..a3af0da275b 100644 --- a/go/vt/vtadmin/http/schemas.go +++ b/go/vt/vtadmin/http/schemas.go @@ -25,7 +25,15 @@ import ( // FindSchema implements the http wrapper for the // /schema/{table}[?cluster=[&cluster=]] route. func FindSchema(ctx context.Context, r Request, api *API) *JSONResponse { - panic("unimplemented!") + vars := r.Vars() + query := r.URL.Query() + + schema, err := api.server.FindSchema(ctx, &vtadminpb.FindSchemaRequest{ + Table: vars["table"], + ClusterIds: query["cluster"], + }) + + return NewJSONResponse(schema, err) } // GetSchema implements the http wrapper for the From b5b0713a608fb36aa3d2d23186b7d52bcd1f299d Mon Sep 17 00:00:00 2001 From: Andrew Mason Date: Thu, 4 Mar 2021 15:40:04 -0500 Subject: [PATCH 3/3] Refactor testutils, add tests for FindSchema Signed-off-by: Andrew Mason --- go/vt/vtadmin/api_test.go | 571 ++++++++++++++++++++++++- go/vt/vtadmin/cluster/cluster_test.go | 67 ++- go/vt/vtadmin/testutil/cluster.go | 67 ++- go/vt/vtadmin/testutil/vtctldclient.go | 15 + 4 files changed, 664 insertions(+), 56 deletions(-) diff --git a/go/vt/vtadmin/api_test.go b/go/vt/vtadmin/api_test.go index a626c2ee03d..c6ed1ce609c 100644 --- a/go/vt/vtadmin/api_test.go +++ b/go/vt/vtadmin/api_test.go @@ -19,6 +19,7 @@ package vtadmin import ( "context" "errors" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -48,6 +49,484 @@ import ( "vitess.io/vitess/go/vt/proto/vttime" ) +func TestFindSchema(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + clusters []vtadmintestutil.TestClusterConfig + req *vtadminpb.FindSchemaRequest + expected *vtadminpb.Schema + shouldErr bool + }{ + { + name: "exact match", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone1-0000000100": { + Response: &vtctldatapb.GetSchemaResponse{ + Schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + }, + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + }, + expected: &vtadminpb.Schema{ + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + Keyspace: "testkeyspace", + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + shouldErr: false, + }, + { + name: "error getting tablets", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + + DBConfig: vtadmintestutil.Dbcfg{ + ShouldErr: true, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + }, + shouldErr: true, + }, + { + name: "error getting keyspaces", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Error: fmt.Errorf("GetKeyspaces: %w", assert.AnError), + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + }, + shouldErr: true, + }, + { + name: "error getting schemas", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone1-0000000100": { + Error: fmt.Errorf("GetSchema: %w", assert.AnError), + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + }, + shouldErr: true, + }, + { + name: "no schema found", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone1-0000000100": { + Response: &vtctldatapb.GetSchemaResponse{ + Schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "othertable", + }, + }, + }, + }, + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + }, + shouldErr: true, + }, + { + name: "ambiguous schema errors", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone1-0000000100": { + Response: &vtctldatapb.GetSchemaResponse{ + Schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + }, + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + { + Cluster: &vtadminpb.Cluster{ + Id: "c2", + Name: "cluster2", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone2-0000000200": { + Response: &vtctldatapb.GetSchemaResponse{ + Schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + }, + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone2", + Uid: 200, + }, + Keyspace: "testkeyspace", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + }, + shouldErr: true, + }, + { + name: "ambiguous schema with request scoped to single cluster passes", + clusters: []vtadmintestutil.TestClusterConfig{ + { + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace1", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone1-0000000100": { + Response: &vtctldatapb.GetSchemaResponse{ + Schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + }, + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace1", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + { + Cluster: &vtadminpb.Cluster{ + Id: "c2", + Name: "cluster2", + }, + VtctldClient: &vtadmintestutil.VtctldClient{ + GetKeyspacesResults: struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + }{ + Keyspaces: []*vtctldatapb.Keyspace{ + { + Name: "testkeyspace2", + }, + }, + }, + GetSchemaResults: map[string]struct { + Response *vtctldatapb.GetSchemaResponse + Error error + }{ + "zone2-0000000200": { + Response: &vtctldatapb.GetSchemaResponse{ + Schema: &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + }, + }, + }, + }, + Tablets: []*vtadminpb.Tablet{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone2", + Uid: 200, + }, + Keyspace: "testkeyspace2", + }, + State: vtadminpb.Tablet_SERVING, + }, + }, + }, + }, + req: &vtadminpb.FindSchemaRequest{ + Table: "testtable", + ClusterIds: []string{"c1"}, + }, + expected: &vtadminpb.Schema{ + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + Keyspace: "testkeyspace1", + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: "testtable", + }, + }, + }, + shouldErr: false, + }, + } + + ctx := context.Background() + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + clusters := make([]*cluster.Cluster, len(tt.clusters)) + for i, cfg := range tt.clusters { + clusters[i] = vtadmintestutil.BuildCluster(cfg) + } + + api := NewAPI(clusters, grpcserver.Options{}, http.Options{}) + + resp, err := api.FindSchema(ctx, tt.req) + if tt.shouldErr { + assert.Error(t, err) + + return + } + + assert.NoError(t, err) + assert.Equal(t, tt.expected, resp) + }) + } +} + func TestGetClusters(t *testing.T) { tests := []struct { name string @@ -395,8 +874,20 @@ func TestGetKeyspaces(t *testing.T) { testutil.WithTestServers(t, func(t *testing.T, clients ...vtctldclient.VtctldClient) { clusters := []*cluster.Cluster{ - vtadmintestutil.BuildCluster(0, clients[0], nil, nil), - vtadmintestutil.BuildCluster(1, clients[1], nil, nil), + vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: "c0", + Name: "cluster0", + }, + VtctldClient: clients[0], + }), + vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: "c1", + Name: "cluster1", + }, + VtctldClient: clients[1], + }), } api := NewAPI(clusters, grpcserver.Options{}, http.Options{}) @@ -612,7 +1103,14 @@ func TestGetSchema(t *testing.T) { testutil.AddTablets(ctx, t, tt.ts, nil, vtadmintestutil.TopodataTabletsFromVTAdminTablets(tt.tablets)...) testutil.WithTestServer(t, vtctld, func(t *testing.T, client vtctldclient.VtctldClient) { - c := vtadmintestutil.BuildCluster(tt.clusterID, client, tt.tablets, nil) + c := vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: fmt.Sprintf("c%d", tt.clusterID), + Name: fmt.Sprintf("cluster%d", tt.clusterID), + }, + VtctldClient: client, + Tablets: tt.tablets, + }) api := NewAPI([]*cluster.Cluster{c}, grpcserver.Options{}, http.Options{}) resp, err := api.GetSchema(ctx, tt.req) @@ -1115,7 +1613,14 @@ func TestGetSchemas(t *testing.T) { } } - clusters[cdx] = vtadmintestutil.BuildCluster(cdx, clients[cdx], cts, nil) + clusters[cdx] = vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: fmt.Sprintf("c%d", cdx), + Name: fmt.Sprintf("cluster%d", cdx), + }, + VtctldClient: clients[cdx], + Tablets: cts, + }) } api := NewAPI(clusters, grpcserver.Options{}, http.Options{}) @@ -1133,7 +1638,7 @@ func TestGetTablets(t *testing.T) { tests := []struct { name string clusterTablets [][]*vtadminpb.Tablet - dbconfigs map[string]*vtadmintestutil.Dbcfg + dbconfigs map[string]vtadmintestutil.Dbcfg req *vtadminpb.GetTabletsRequest expected []*vtadminpb.Tablet shouldErr bool @@ -1158,7 +1663,7 @@ func TestGetTablets(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{}, + dbconfigs: map[string]vtadmintestutil.Dbcfg{}, req: &vtadminpb.GetTabletsRequest{}, expected: []*vtadminpb.Tablet{ { @@ -1217,7 +1722,7 @@ func TestGetTablets(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{ + dbconfigs: map[string]vtadmintestutil.Dbcfg{ "c1": {ShouldErr: true}, }, req: &vtadminpb.GetTabletsRequest{}, @@ -1260,7 +1765,7 @@ func TestGetTablets(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{}, + dbconfigs: map[string]vtadmintestutil.Dbcfg{}, req: &vtadminpb.GetTabletsRequest{ClusterIds: []string{"c0"}}, expected: []*vtadminpb.Tablet{ { @@ -1290,8 +1795,17 @@ func TestGetTablets(t *testing.T) { clusters := make([]*cluster.Cluster, len(tt.clusterTablets)) for i, tablets := range tt.clusterTablets { - cluster := vtadmintestutil.BuildCluster(i, nil, tablets, tt.dbconfigs) - clusters[i] = cluster + cid := fmt.Sprintf("c%d", i) + dbconfigs := tt.dbconfigs[cid] + + clusters[i] = vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: cid, + Name: fmt.Sprintf("cluster%d", i), + }, + Tablets: tablets, + DBConfig: dbconfigs, + }) } api := NewAPI(clusters, grpcserver.Options{}, http.Options{}) @@ -1311,7 +1825,7 @@ func TestGetTablet(t *testing.T) { tests := []struct { name string clusterTablets [][]*vtadminpb.Tablet - dbconfigs map[string]*vtadmintestutil.Dbcfg + dbconfigs map[string]vtadmintestutil.Dbcfg req *vtadminpb.GetTabletRequest expected *vtadminpb.Tablet shouldErr bool @@ -1336,7 +1850,7 @@ func TestGetTablet(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{}, + dbconfigs: map[string]vtadmintestutil.Dbcfg{}, req: &vtadminpb.GetTabletRequest{ Hostname: "ks1-00-00-zone1-a", }, @@ -1395,7 +1909,7 @@ func TestGetTablet(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{ + dbconfigs: map[string]vtadmintestutil.Dbcfg{ "c1": {ShouldErr: true}, }, req: &vtadminpb.GetTabletRequest{ @@ -1440,7 +1954,7 @@ func TestGetTablet(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{}, + dbconfigs: map[string]vtadmintestutil.Dbcfg{}, req: &vtadminpb.GetTabletRequest{ Hostname: "ks1-00-00-zone1-a", ClusterIds: []string{"c0"}, @@ -1500,7 +2014,7 @@ func TestGetTablet(t *testing.T) { }, }, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{}, + dbconfigs: map[string]vtadmintestutil.Dbcfg{}, req: &vtadminpb.GetTabletRequest{ Hostname: "ks1-00-00-zone1-a", }, @@ -1513,7 +2027,7 @@ func TestGetTablet(t *testing.T) { /* cluster 0 */ {}, }, - dbconfigs: map[string]*vtadmintestutil.Dbcfg{}, + dbconfigs: map[string]vtadmintestutil.Dbcfg{}, req: &vtadminpb.GetTabletRequest{ Hostname: "ks1-00-00-zone1-a", }, @@ -1527,8 +2041,17 @@ func TestGetTablet(t *testing.T) { clusters := make([]*cluster.Cluster, len(tt.clusterTablets)) for i, tablets := range tt.clusterTablets { - cluster := vtadmintestutil.BuildCluster(i, nil, tablets, tt.dbconfigs) - clusters[i] = cluster + cid := fmt.Sprintf("c%d", i) + dbconfigs := tt.dbconfigs[cid] + + clusters[i] = vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: cid, + Name: fmt.Sprintf("cluster%d", i), + }, + Tablets: tablets, + DBConfig: dbconfigs, + }) } api := NewAPI(clusters, grpcserver.Options{}, http.Options{}) @@ -1802,8 +2325,16 @@ func TestVTExplain(t *testing.T) { } } - c := vtadmintestutil.BuildCluster(0, vtctldClient, tt.tablets, nil) - clusters := []*cluster.Cluster{c} + clusters := []*cluster.Cluster{ + vtadmintestutil.BuildCluster(vtadmintestutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: "c0", + Name: "cluster0", + }, + VtctldClient: vtctldClient, + Tablets: tt.tablets, + }), + } api := NewAPI(clusters, grpcserver.Options{}, http.Options{}) resp, err := api.VTExplain(context.Background(), tt.req) diff --git a/go/vt/vtadmin/cluster/cluster_test.go b/go/vt/vtadmin/cluster/cluster_test.go index be2fab67b76..d374234ab1b 100644 --- a/go/vt/vtadmin/cluster/cluster_test.go +++ b/go/vt/vtadmin/cluster/cluster_test.go @@ -20,6 +20,7 @@ import ( "context" "database/sql" "errors" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -178,7 +179,15 @@ func TestGetSchema(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - cluster := testutil.BuildCluster(i, tt.vtctld, nil, nil) + cluster := testutil.BuildCluster(testutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: fmt.Sprintf("c%d", i), + Name: fmt.Sprintf("cluster%d", i), + }, + VtctldClient: tt.vtctld, + Tablets: nil, + DBConfig: testutil.Dbcfg{}, + }) ctx := context.Background() err := cluster.Vtctld.Dial(ctx) @@ -226,7 +235,13 @@ func TestGetSchema(t *testing.T) { }, } - cluster := testutil.BuildCluster(0, vtctld, nil, nil) + cluster := testutil.BuildCluster(testutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: "c0", + Name: "cluster0", + }, + VtctldClient: vtctld, + }) err := cluster.Vtctld.Dial(ctx) require.NoError(t, err, "could not dial test vtctld") @@ -419,12 +434,24 @@ func TestFindTablets(t *testing.T) { }, } + ctx := context.Background() + for _, tt := range tests { - cluster := testutil.BuildCluster(0, nil, tt.tablets, nil) - tablets, err := cluster.FindTablets(context.Background(), tt.filter, tt.n) + tt := tt - assert.NoError(t, err) - testutil.AssertTabletSlicesEqual(t, tt.expected, tablets) + t.Run(tt.name, func(t *testing.T) { + cluster := testutil.BuildCluster(testutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: "c0", + Name: "cluster0", + }, + Tablets: tt.tablets, + }) + tablets, err := cluster.FindTablets(ctx, tt.filter, tt.n) + + assert.NoError(t, err) + testutil.AssertTabletSlicesEqual(t, tt.expected, tablets) + }) } } @@ -520,15 +547,27 @@ func TestFindTablet(t *testing.T) { }, } + ctx := context.Background() + for _, tt := range tests { - cluster := testutil.BuildCluster(0, nil, tt.tablets, nil) - tablet, err := cluster.FindTablet(context.Background(), tt.filter) + tt := tt - if tt.expectedError != nil { - assert.True(t, errors.Is(err, tt.expectedError), "expected error type %w does not match actual error type %w", err, tt.expectedError) - } else { - assert.NoError(t, err) - testutil.AssertTabletsEqual(t, tt.expected, tablet) - } + t.Run(tt.name, func(t *testing.T) { + cluster := testutil.BuildCluster(testutil.TestClusterConfig{ + Cluster: &vtadminpb.Cluster{ + Id: "c0", + Name: "cluster0", + }, + Tablets: tt.tablets, + }) + tablet, err := cluster.FindTablet(ctx, tt.filter) + + if tt.expectedError != nil { + assert.True(t, errors.Is(err, tt.expectedError), "expected error type %w does not match actual error type %w", err, tt.expectedError) + } else { + assert.NoError(t, err) + testutil.AssertTabletsEqual(t, tt.expected, tablet) + } + }) } } diff --git a/go/vt/vtadmin/testutil/cluster.go b/go/vt/vtadmin/testutil/cluster.go index 6c7fea37a9d..d8e8a04eac3 100644 --- a/go/vt/vtadmin/testutil/cluster.go +++ b/go/vt/vtadmin/testutil/cluster.go @@ -40,43 +40,66 @@ type Dbcfg struct { ShouldErr bool } -// BuildCluster is a shared helper for building a cluster that contains the given tablets and -// talking to the given vtctld server. dbconfigs contains an optional config -// for controlling the behavior of the cluster's DB at the package sql level. -func BuildCluster(i int, vtctldClient vtctldclient.VtctldClient, tablets []*vtadminpb.Tablet, dbconfigs map[string]*Dbcfg) *cluster.Cluster { +// TestClusterConfig controls the way that a cluster.Cluster object is +// constructed for testing vtadmin code. +type TestClusterConfig struct { + // Cluster provides the protobuf-based version of the cluster info. It is + // to set the ID and Name of the resulting cluster.Cluster, as well as to + // name a single, phony, vtgate entry in the cluster's discovery service. + Cluster *vtadminpb.Cluster + // VtctldClient provides the vtctldclient.VtctldClient implementation the + // cluster's vtctld proxy will use. Most unit tests will use an instance of + // the VtctldClient type provided by this package in order to mock out the + // vtctld layer. + VtctldClient vtctldclient.VtctldClient + // Tablets provides the set of tablets reachable by this cluster's vtsql.DB. + // Tablets are copied, and then mutated to have their Cluster field set to + // match the Cluster provided by this TestClusterConfig, so mutations are + // transparent to the caller. + Tablets []*vtadminpb.Tablet + // DBConfig controls the behavior of the cluster's vtsql.DB. + DBConfig Dbcfg +} + +// BuildCluster is a shared helper for building a cluster based on the given +// test configuration. +func BuildCluster(cfg TestClusterConfig) *cluster.Cluster { disco := fakediscovery.New() - disco.AddTaggedGates(nil, &vtadminpb.VTGate{Hostname: fmt.Sprintf("cluster%d-gate", i)}) + disco.AddTaggedGates(nil, &vtadminpb.VTGate{Hostname: fmt.Sprintf("%s-%s-gate", cfg.Cluster.Name, cfg.Cluster.Id)}) disco.AddTaggedVtctlds(nil, &vtadminpb.Vtctld{Hostname: "doesn't matter"}) - cluster := &cluster.Cluster{ - ID: fmt.Sprintf("c%d", i), - Name: fmt.Sprintf("cluster%d", i), - Discovery: disco, - } + tablets := make([]*vtadminpb.Tablet, len(cfg.Tablets)) + for i, t := range cfg.Tablets { + tablet := &vtadminpb.Tablet{ + Cluster: cfg.Cluster, + Tablet: t.Tablet, + State: t.State, + } - dbconfig, ok := dbconfigs[cluster.ID] - if !ok { - dbconfig = &Dbcfg{ShouldErr: false} + tablets[i] = tablet } db := vtsql.New(&vtsql.Config{ - Cluster: cluster.ToProto(), + Cluster: cfg.Cluster, Discovery: disco, }) - db.DialFunc = func(cfg vitessdriver.Configuration) (*sql.DB, error) { - return sql.OpenDB(&fakevtsql.Connector{Tablets: tablets, ShouldErr: dbconfig.ShouldErr}), nil + db.DialFunc = func(_ vitessdriver.Configuration) (*sql.DB, error) { + return sql.OpenDB(&fakevtsql.Connector{Tablets: tablets, ShouldErr: cfg.DBConfig.ShouldErr}), nil } vtctld := vtadminvtctldclient.New(&vtadminvtctldclient.Config{ - Cluster: cluster.ToProto(), + Cluster: cfg.Cluster, Discovery: disco, }) vtctld.DialFunc = func(addr string, ff grpcclient.FailFast, opts ...grpc.DialOption) (vtctldclient.VtctldClient, error) { - return vtctldClient, nil + return cfg.VtctldClient, nil } - cluster.DB = db - cluster.Vtctld = vtctld - - return cluster + return &cluster.Cluster{ + ID: cfg.Cluster.Id, + Name: cfg.Cluster.Name, + Discovery: disco, + DB: db, + Vtctld: vtctld, + } } diff --git a/go/vt/vtadmin/testutil/vtctldclient.go b/go/vt/vtadmin/testutil/vtctldclient.go index 70a5c88698f..c93354a6a72 100644 --- a/go/vt/vtadmin/testutil/vtctldclient.go +++ b/go/vt/vtadmin/testutil/vtctldclient.go @@ -34,6 +34,10 @@ import ( type VtctldClient struct { vtctldclient.VtctldClient + GetKeyspacesResults struct { + Keyspaces []*vtctldatapb.Keyspace + Error error + } GetSchemaResults map[string]struct { Response *vtctldatapb.GetSchemaResponse Error error @@ -44,6 +48,17 @@ type VtctldClient struct { // incorrectly. var _ vtctldclient.VtctldClient = (*VtctldClient)(nil) +// GetKeyspaces is part of the vtctldclient.VtctldClient interface. +func (fake *VtctldClient) GetKeyspaces(ctx context.Context, req *vtctldatapb.GetKeyspacesRequest, opts ...grpc.CallOption) (*vtctldatapb.GetKeyspacesResponse, error) { + if fake.GetKeyspacesResults.Error != nil { + return nil, fake.GetKeyspacesResults.Error + } + + return &vtctldatapb.GetKeyspacesResponse{ + Keyspaces: fake.GetKeyspacesResults.Keyspaces, + }, nil +} + // GetSchema is part of the vtctldclient.VtctldClient interface. func (fake *VtctldClient) GetSchema(ctx context.Context, req *vtctldatapb.GetSchemaRequest, opts ...grpc.CallOption) (*vtctldatapb.GetSchemaResponse, error) { if fake.GetSchemaResults == nil {