diff --git a/pkg/apiserver/debugapi/endpoint/models.go b/pkg/apiserver/debugapi/endpoint/models.go index 6b504a1df3..ebc56bfbcc 100644 --- a/pkg/apiserver/debugapi/endpoint/models.go +++ b/pkg/apiserver/debugapi/endpoint/models.go @@ -15,7 +15,7 @@ import ( // APIDefinition can be "resolved" to become a request when its parameter values are given via RequestPayload. type APIDefinition struct { ID string `json:"id"` - Component topo.ComponentKind `json:"component"` + Component topo.Kind `json:"component"` Path string `json:"path"` Method string `json:"method"` PathParams []APIParamDefinition `json:"path_params"` // e.g. /stats/dump/{db}/{table} -> db, table diff --git a/pkg/apiserver/debugapi/endpoint/payload.go b/pkg/apiserver/debugapi/endpoint/payload.go index c3fe98d739..3039fd3d2f 100644 --- a/pkg/apiserver/debugapi/endpoint/payload.go +++ b/pkg/apiserver/debugapi/endpoint/payload.go @@ -35,7 +35,7 @@ type HTTPClients struct { TiFlashStatusClient *tiflashclient.StatusClient } -func (c HTTPClients) GetHTTPClientByNodeKind(kind topo.ComponentKind) *httpclient.Client { +func (c HTTPClients) GetHTTPClientByNodeKind(kind topo.Kind) *httpclient.Client { switch kind { case topo.KindPD: if c.PDAPIClient == nil { diff --git a/util/client/pdclient/fixture/pd_server.go b/util/client/pdclient/fixture/pd_server.go index 1e690feb4a..2173f04025 100644 --- a/util/client/pdclient/fixture/pd_server.go +++ b/util/client/pdclient/fixture/pd_server.go @@ -3,23 +3,19 @@ package fixture import ( - "strings" - "github.com/jarcoal/httpmock" "github.com/pingcap/tidb-dashboard/util/client/httpclient" "github.com/pingcap/tidb-dashboard/util/client/pdclient" + "github.com/pingcap/tidb-dashboard/util/testutil/httpmockutil" ) -func newResponder(body string) httpmock.Responder { - return httpmock.NewStringResponder(200, strings.TrimSpace(body)) -} +const BaseURL = "http://172.16.6.171:2379" -func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string) { - baseURL = "http://172.16.6.171:2379" +func NewPDServerFixture() (mockTransport *httpmock.MockTransport) { mockTransport = httpmock.NewMockTransport() mockTransport.RegisterResponder("GET", "http://172.16.6.171:2379/pd/api/v1/status", - newResponder(` + httpmockutil.StringResponder(` { "build_ts": "2021-07-17 05:37:05", "version": "v4.0.14", @@ -28,7 +24,7 @@ func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string } `)) mockTransport.RegisterResponder("GET", "http://172.16.6.171:2379/pd/api/v1/health", - newResponder(` + httpmockutil.StringResponder(` [ { "name": "pd-172.16.6.170-2379", @@ -57,7 +53,7 @@ func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string ] `)) mockTransport.RegisterResponder("GET", "http://172.16.6.171:2379/pd/api/v1/members", - newResponder(` + httpmockutil.StringResponder(` { "header": { "cluster_id": 6973530669239952773 @@ -129,7 +125,7 @@ func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string } `)) mockTransport.RegisterResponder("GET", "http://172.16.6.171:2379/pd/api/v1/stores", - newResponder(` + httpmockutil.StringResponder(` { "count": 3, "stores": [ @@ -224,7 +220,7 @@ func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string } `)) mockTransport.RegisterResponder("GET", "http://172.16.6.171:2379/pd/api/v1/config", - newResponder(` + httpmockutil.StringResponder(` { "client-urls": "http://0.0.0.0:2379", "peer-urls": "http://0.0.0.0:2380", @@ -418,7 +414,7 @@ func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string } `)) mockTransport.RegisterResponder("GET", "http://172.16.6.171:2379/pd/api/v1/config/replicate", - newResponder(` + httpmockutil.StringResponder(` { "max-replicas": 3, "location-labels": "", @@ -429,12 +425,11 @@ func NewPDServerFixture() (mockTransport *httpmock.MockTransport, baseURL string return } -func NewAPIAPIClientFixture() *pdclient.APIClient { - mockTransport, baseURL := NewPDServerFixture() +// NewAPIClientFixture returns a PD client whose default Base URL is pointing to a mock PD server. +func NewAPIClientFixture() *pdclient.APIClient { + mockTransport := NewPDServerFixture() apiClient := pdclient.NewAPIClient(httpclient.Config{}) - apiClient. - SetDefaultTransport(mockTransport). - SetDefaultBaseURL(baseURL) - + apiClient.SetDefaultBaseURL(BaseURL) + apiClient.SetDefaultTransport(mockTransport) return apiClient } diff --git a/util/client/pdclient/pd_api.go b/util/client/pdclient/pd_api.go index 98a0534f60..e4bc26dd86 100644 --- a/util/client/pdclient/pd_api.go +++ b/util/client/pdclient/pd_api.go @@ -2,7 +2,9 @@ package pdclient -import "context" +import ( + "context" +) // TODO: Switch to use swagger. @@ -13,7 +15,7 @@ type GetStatusResponse struct { } // GetStatus returns the content from /status PD API. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) GetStatus(ctx context.Context) (resp *GetStatusResponse, err error) { _, err = api.LR().SetContext(ctx).Get(APIPrefix + "/status").ReadBodyAsJSON(&resp) return @@ -27,7 +29,7 @@ type GetHealthResponseMember struct { type GetHealthResponse []GetHealthResponseMember // GetHealth returns the content from /health PD API. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) GetHealth(ctx context.Context) (resp *GetHealthResponse, err error) { _, err = api.LR().SetContext(ctx).Get(APIPrefix + "/health").ReadBodyAsJSON(&resp) return @@ -46,7 +48,7 @@ type GetMembersResponse struct { } // GetMembers returns the content from /members PD API. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) GetMembers(ctx context.Context) (resp *GetMembersResponse, err error) { _, err = api.LR().SetContext(ctx).Get(APIPrefix + "/members").ReadBodyAsJSON(&resp) return @@ -57,7 +59,7 @@ type GetConfigReplicateResponse struct { } // GetConfigReplicate returns the content from /config/replicate PD API. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) GetConfigReplicate(ctx context.Context) (resp *GetConfigReplicateResponse, err error) { _, err = api.LR().SetContext(ctx).Get(APIPrefix + "/config/replicate").ReadBodyAsJSON(&resp) return @@ -89,7 +91,7 @@ type GetStoresResponse struct { } // GetStores returns the content from /stores PD API. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) GetStores(ctx context.Context) (resp *GetStoresResponse, err error) { _, err = api.LR().SetContext(ctx).Get(APIPrefix + "/stores").ReadBodyAsJSON(&resp) return diff --git a/util/client/pdclient/pd_api_highlevel.go b/util/client/pdclient/pd_api_highlevel.go index ae8acc02d0..baac994f43 100644 --- a/util/client/pdclient/pd_api_highlevel.go +++ b/util/client/pdclient/pd_api_highlevel.go @@ -11,7 +11,7 @@ import ( ) // HLGetStores returns all stores in PD in order. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) HLGetStores(ctx context.Context) ([]GetStoresResponseStore, error) { resp, err := api.GetStores(ctx) if err != nil { @@ -28,7 +28,7 @@ func (api *APIClient) HLGetStores(ctx context.Context) ([]GetStoresResponseStore } // HLGetLocationLabels returns the location label config in PD. -// An optional ctx can be passed in to override the default context. To keep the default context, pass nil. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) HLGetLocationLabels(ctx context.Context) ([]string, error) { resp, err := api.GetConfigReplicate(ctx) if err != nil { @@ -51,6 +51,8 @@ type StoreLocations struct { Stores []StoreLabels `json:"stores"` } +// HLGetStoreLocations returns the stores and their locations. +// You must specify the base URL by calling SetDefaultBaseURL() before using this function. func (api *APIClient) HLGetStoreLocations(ctx context.Context) (*StoreLocations, error) { locationLabels, err := api.HLGetLocationLabels(ctx) if err != nil { diff --git a/util/client/pdclient/pd_api_highlevel_test.go b/util/client/pdclient/pd_api_highlevel_test.go index 1f1d35e4f6..9033a3cdc3 100644 --- a/util/client/pdclient/pd_api_highlevel_test.go +++ b/util/client/pdclient/pd_api_highlevel_test.go @@ -13,14 +13,14 @@ import ( ) func TestAPIClient_HLGetLocationLabels(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.HLGetLocationLabels(context.Background()) require.NoError(t, err) require.Equal(t, []string{}, resp) } func TestAPIClient_HLGetStoreLocations(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.HLGetStoreLocations(context.Background()) require.NoError(t, err) require.Equal(t, &pdclient.StoreLocations{ @@ -34,7 +34,7 @@ func TestAPIClient_HLGetStoreLocations(t *testing.T) { } func TestAPIClient_HLGetStores(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.HLGetStores(context.Background()) require.NoError(t, err) require.Equal(t, []pdclient.GetStoresResponseStore{ diff --git a/util/client/pdclient/pd_api_test.go b/util/client/pdclient/pd_api_test.go index d0afba17d4..ac1b70b8bc 100644 --- a/util/client/pdclient/pd_api_test.go +++ b/util/client/pdclient/pd_api_test.go @@ -13,7 +13,7 @@ import ( ) func TestAPIClient_GetConfigReplicate(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.GetConfigReplicate(context.Background()) require.NoError(t, err) require.Equal(t, &pdclient.GetConfigReplicateResponse{ @@ -22,7 +22,7 @@ func TestAPIClient_GetConfigReplicate(t *testing.T) { } func TestAPIClient_GetHealth(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.GetHealth(context.Background()) require.NoError(t, err) require.Equal(t, &pdclient.GetHealthResponse{ @@ -33,7 +33,7 @@ func TestAPIClient_GetHealth(t *testing.T) { } func TestAPIClient_GetMembers(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.GetMembers(context.Background()) require.NoError(t, err) require.Equal(t, &pdclient.GetMembersResponse{ @@ -62,7 +62,7 @@ func TestAPIClient_GetMembers(t *testing.T) { } func TestAPIClient_GetStatus(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.GetStatus(context.Background()) require.NoError(t, err) require.Equal(t, &pdclient.GetStatusResponse{ @@ -71,7 +71,7 @@ func TestAPIClient_GetStatus(t *testing.T) { } func TestAPIClient_GetStores(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := apiClient.GetStores(context.Background()) require.NoError(t, err) require.Equal(t, &pdclient.GetStoresResponse{ diff --git a/util/topo/model.go b/util/topo/model.go new file mode 100644 index 0000000000..8aa0be2de9 --- /dev/null +++ b/util/topo/model.go @@ -0,0 +1,176 @@ +// Copyright 2022 PingCAP, Inc. Licensed under Apache-2.0. + +package topo + +type CompStatus string + +const ( + CompStatusUnknown CompStatus = "unknown" + CompStatusUnreachable CompStatus = "unreachable" + CompStatusUp CompStatus = "up" + CompStatusTombstone CompStatus = "tombstone" + CompStatusLeaving CompStatus = "leaving" + CompStatusDown CompStatus = "down" +) + +type Kind string + +const ( + KindTiDB Kind = "tidb" + KindTiKV Kind = "tikv" + KindPD Kind = "pd" + KindTiFlash Kind = "tiflash" + KindAlertManager Kind = "alert_manager" + KindGrafana Kind = "grafana" + KindPrometheus Kind = "prometheus" +) + +type PDInfo struct { + GitHash string + Version string + IP string + Port uint + DeployPath string + Status CompStatus + StartTimestamp int64 // Ts = 0 means unknown +} + +var _ Info = &PDInfo{} + +func (i *PDInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + Kind: KindPD, + }, + Version: i.Version, + Status: i.Status, + } +} + +type TiDBInfo struct { + GitHash string + Version string + IP string + Port uint + DeployPath string + Status CompStatus + StatusPort uint + StartTimestamp int64 +} + +var _ Info = &TiDBInfo{} + +func (i *TiDBInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + StatusPort: i.StatusPort, + Kind: KindTiDB, + }, + Version: i.Version, + Status: i.Status, + } +} + +// StoreInfo may be either a TiKV store info or a TiFlash store info. +type StoreInfo struct { + GitHash string + Version string + IP string + Port uint + DeployPath string + Status CompStatus + StatusPort uint + Labels map[string]string + StartTimestamp int64 +} + +type TiKVStoreInfo StoreInfo + +var _ Info = &TiKVStoreInfo{} + +func (i *TiKVStoreInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + StatusPort: i.StatusPort, + Kind: KindTiKV, + }, + Version: i.Version, + Status: i.Status, + } +} + +type TiFlashStoreInfo StoreInfo + +var _ Info = &TiFlashStoreInfo{} + +func (i *TiFlashStoreInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + StatusPort: i.StatusPort, + Kind: KindTiFlash, + }, + Version: i.Version, + Status: i.Status, + } +} + +type StandardDeployInfo struct { + IP string + Port uint +} + +type AlertManagerInfo StandardDeployInfo + +var _ Info = &AlertManagerInfo{} + +func (i *AlertManagerInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + Kind: KindAlertManager, + }, + Version: "", + Status: CompStatusUnknown, + } +} + +type GrafanaInfo StandardDeployInfo + +var _ Info = &GrafanaInfo{} + +func (i *GrafanaInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + Kind: KindGrafana, + }, + Version: "", + Status: CompStatusUnknown, + } +} + +type PrometheusInfo StandardDeployInfo + +var _ Info = &PrometheusInfo{} + +func (i *PrometheusInfo) Info() CompInfo { + return CompInfo{ + CompDescriptor: CompDescriptor{ + IP: i.IP, + Port: i.Port, + Kind: KindPrometheus, + }, + Version: "", + Status: CompStatusUnknown, + } +} diff --git a/util/topo/model_desc.go b/util/topo/model_desc.go new file mode 100644 index 0000000000..e4bf58c02d --- /dev/null +++ b/util/topo/model_desc.go @@ -0,0 +1,15 @@ +// Copyright 2022 PingCAP, Inc. Licensed under Apache-2.0. + +package topo + +// CompDescriptor (Component Desc) is a unique identifier for a component. +// It is secure to be persisted, but is not secure to be accepted from the user input. +// To securely accept a Comp from user input, see SignedCompDescriptor. +type CompDescriptor struct { + IP string + Port uint + StatusPort uint + Kind Kind + // WARN: Extreme care should be taken when adding more fields here, + // as this struct is widely used or persisted. +} diff --git a/util/topo/model_info.go b/util/topo/model_info.go new file mode 100644 index 0000000000..6a126afa5c --- /dev/null +++ b/util/topo/model_info.go @@ -0,0 +1,89 @@ +// Copyright 2022 PingCAP, Inc. Licensed under Apache-2.0. + +package topo + +import ( + "context" + "fmt" +) + +// CompInfo provides common information for a component. +// It must not be persisted, as the runtime status may change at any time. +// It must not be accepted directly from the user input. See SignedCompDescriptor. +// The contained descriptor is unsigned, which means it may not be very useful to be passed to users. +// Call WithSignature() if you want to pass to users. +type CompInfo struct { + CompDescriptor + Version string + Status CompStatus +} + +// Info is an interface implemented by all component info structures. +type Info interface { + Info() CompInfo +} + +func GetInfoByKind(ctx context.Context, p TopologyProvider, kind Kind) ([]CompInfo, error) { + switch kind { + case KindTiDB: + v, err := p.GetTiDB(ctx) + if err != nil { + return nil, err + } + result := make([]CompInfo, 0, len(v)) + for _, info := range v { + result = append(result, info.Info()) + } + return result, nil + case KindTiKV: + v, err := p.GetTiKV(ctx) + if err != nil { + return nil, err + } + result := make([]CompInfo, 0, len(v)) + for _, info := range v { + result = append(result, info.Info()) + } + return result, nil + case KindPD: + v, err := p.GetPD(ctx) + if err != nil { + return nil, err + } + result := make([]CompInfo, 0, len(v)) + for _, info := range v { + result = append(result, info.Info()) + } + return result, nil + case KindTiFlash: + v, err := p.GetTiFlash(ctx) + if err != nil { + return nil, err + } + result := make([]CompInfo, 0, len(v)) + for _, info := range v { + result = append(result, info.Info()) + } + return result, nil + case KindAlertManager: + v, err := p.GetAlertManager(ctx) + if err != nil { + return nil, err + } + return []CompInfo{v.Info()}, nil + case KindGrafana: + v, err := p.GetGrafana(ctx) + if err != nil { + return nil, err + } + return []CompInfo{v.Info()}, nil + case KindPrometheus: + v, err := p.GetPrometheus(ctx) + if err != nil { + return nil, err + } + return []CompInfo{v.Info()}, nil + default: + return nil, fmt.Errorf("unsupported component %s", kind) + } +} diff --git a/util/topo/models.go b/util/topo/models.go deleted file mode 100644 index 9ac596f660..0000000000 --- a/util/topo/models.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2022 PingCAP, Inc. Licensed under Apache-2.0. - -package topo - -type ComponentStatus uint - -const ( - ComponentStatusUnreachable ComponentStatus = 0 - ComponentStatusUp ComponentStatus = 1 - ComponentStatusTombstone ComponentStatus = 2 - ComponentStatusOffline ComponentStatus = 3 - ComponentStatusDown ComponentStatus = 4 -) - -type ComponentKind string - -const ( - KindTiDB ComponentKind = "tidb" - KindTiKV ComponentKind = "tikv" - KindPD ComponentKind = "pd" - KindTiFlash ComponentKind = "tiflash" - KindAlertManager ComponentKind = "alert_manager" - KindGrafana ComponentKind = "grafana" - KindPrometheus ComponentKind = "prometheus" -) - -type ComponentDescriptor struct { - IP string `json:"ip"` - Port uint `json:"port"` - Kind ComponentKind `json:"kind"` -} - -type PDInfo struct { - GitHash string `json:"git_hash"` - Version string `json:"version"` - IP string `json:"ip"` - Port uint `json:"port"` - DeployPath string `json:"deploy_path"` - Status ComponentStatus `json:"status"` - StartTimestamp int64 `json:"start_timestamp"` // Ts = 0 means unknown -} - -func (i *PDInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindPD, - } -} - -type TiDBInfo struct { - GitHash string `json:"git_hash"` - Version string `json:"version"` - IP string `json:"ip"` - Port uint `json:"port"` - DeployPath string `json:"deploy_path"` - Status ComponentStatus `json:"status"` - StatusPort uint `json:"status_port"` - StartTimestamp int64 `json:"start_timestamp"` -} - -func (i *TiDBInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindTiDB, - } -} - -// StoreInfo may be either a TiKV store info or a TiFlash store info. -type StoreInfo struct { - GitHash string `json:"git_hash"` - Version string `json:"version"` - IP string `json:"ip"` - Port uint `json:"port"` - DeployPath string `json:"deploy_path"` - Status ComponentStatus `json:"status"` - StatusPort uint `json:"status_port"` - Labels map[string]string `json:"labels"` - StartTimestamp int64 `json:"start_timestamp"` -} - -type TiKVStoreInfo StoreInfo - -func (i *TiKVStoreInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindTiKV, - } -} - -type TiFlashStoreInfo StoreInfo - -func (i *TiFlashStoreInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindTiFlash, - } -} - -type StandardComponentInfo struct { - IP string `json:"ip"` - Port uint `json:"port"` -} - -type AlertManagerInfo StandardComponentInfo - -func (i *AlertManagerInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindAlertManager, - } -} - -type GrafanaInfo StandardComponentInfo - -func (i *GrafanaInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindGrafana, - } -} - -type PrometheusInfo StandardComponentInfo - -func (i *PrometheusInfo) Describe() ComponentDescriptor { - return ComponentDescriptor{ - IP: i.IP, - Port: i.Port, - Kind: KindPrometheus, - } -} diff --git a/util/topo/pdtopo/pd.go b/util/topo/pdtopo/pd.go index f351cd1ba2..d13c2b5b00 100644 --- a/util/topo/pdtopo/pd.go +++ b/util/topo/pdtopo/pd.go @@ -50,9 +50,9 @@ func GetPDInstances(ctx context.Context, pdAPI *pdclient.APIClient) ([]topo.PDIn tsResp = &pdclient.GetStatusResponse{} } - storeStatus := topo.ComponentStatusUnreachable + storeStatus := topo.CompStatusUnreachable if _, ok := healthMap[ds.MemberID]; ok { - storeStatus = topo.ComponentStatusUp + storeStatus = topo.CompStatusUp } nodes = append(nodes, topo.PDInfo{ diff --git a/util/topo/pdtopo/pd_test.go b/util/topo/pdtopo/pd_test.go index b744ce7f4f..95e7c57279 100644 --- a/util/topo/pdtopo/pd_test.go +++ b/util/topo/pdtopo/pd_test.go @@ -14,7 +14,7 @@ import ( ) func TestGetPDInstances(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() resp, err := pdtopo.GetPDInstances(context.Background(), apiClient) require.NoError(t, err) require.Equal(t, []topo.PDInfo{ @@ -24,7 +24,7 @@ func TestGetPDInstances(t *testing.T) { IP: "172.16.6.169", Port: 2379, DeployPath: "/home/tidb/tidb-deploy/pd-2379/bin", - Status: topo.ComponentStatusUp, + Status: topo.CompStatusUp, StartTimestamp: 1635762685, }, topo.PDInfo{ @@ -33,7 +33,7 @@ func TestGetPDInstances(t *testing.T) { IP: "172.16.6.170", Port: 2379, DeployPath: "/home/tidb/tidb-deploy/pd-2379/bin", - Status: topo.ComponentStatusUp, + Status: topo.CompStatusUp, StartTimestamp: 1635762685, }, topo.PDInfo{ @@ -42,7 +42,7 @@ func TestGetPDInstances(t *testing.T) { IP: "172.16.6.171", Port: 2379, DeployPath: "/home/tidb/tidb-deploy/pd-2379/bin", - Status: topo.ComponentStatusUp, + Status: topo.CompStatusUp, StartTimestamp: 1635762685, }, }, resp) diff --git a/util/topo/pdtopo/provider_pd.go b/util/topo/pdtopo/provider_pd.go index b972bc90ff..c9f2eb6f54 100644 --- a/util/topo/pdtopo/provider_pd.go +++ b/util/topo/pdtopo/provider_pd.go @@ -19,7 +19,9 @@ type TopologyFromPD struct { var _ topo.TopologyProvider = (*TopologyFromPD)(nil) -func NewTopologyProviderFromPD(etcdClient *clientv3.Client, pdAPI *pdclient.APIClient) *TopologyFromPD { +// NewTopologyProviderFromPD creates a provider that gets topology information from PD. +// The base URL of the PD API client must be correctly set. +func NewTopologyProviderFromPD(etcdClient *clientv3.Client, pdAPI *pdclient.APIClient) topo.TopologyProvider { return &TopologyFromPD{ etcdClient: etcdClient, pdAPI: pdAPI, diff --git a/util/topo/pdtopo/std_comp.go b/util/topo/pdtopo/std_comp.go index b6f5a3e891..40cf5b81ac 100644 --- a/util/topo/pdtopo/std_comp.go +++ b/util/topo/pdtopo/std_comp.go @@ -20,7 +20,7 @@ var ( ErrInvalidTopologyData = ErrNS.NewType("invalid_topology_data") ) -func fetchStandardComponentTopology(ctx context.Context, componentName string, etcdClient *clientv3.Client) (*topo.StandardComponentInfo, error) { +func fetchStandardComponentTopology(ctx context.Context, componentName string, etcdClient *clientv3.Client) (*topo.StandardDeployInfo, error) { key := "/topology/" + componentName resp, err := etcdClient.Get(ctx, key, clientv3.WithPrefix()) if err != nil { @@ -29,7 +29,7 @@ func fetchStandardComponentTopology(ctx context.Context, componentName string, e if resp.Count == 0 { return nil, nil } - info := topo.StandardComponentInfo{} + info := topo.StandardDeployInfo{} kv := resp.Kvs[0] if err = json.Unmarshal(kv.Value, &info); err != nil { log.Warn("Failed to unmarshal topology value", diff --git a/util/topo/pdtopo/store.go b/util/topo/pdtopo/store.go index 8706445af1..018ab07019 100644 --- a/util/topo/pdtopo/store.go +++ b/util/topo/pdtopo/store.go @@ -91,20 +91,20 @@ func buildStoreTopology(stores []pdclient.GetStoresResponseStore) []topo.StoreIn return nodes } -func parseStoreState(state string) topo.ComponentStatus { +func parseStoreState(state string) topo.CompStatus { state = strings.Trim(strings.ToLower(state), "\n ") switch state { case "up": - return topo.ComponentStatusUp + return topo.CompStatusUp case "tombstone": - return topo.ComponentStatusTombstone + return topo.CompStatusTombstone case "offline": - return topo.ComponentStatusOffline + return topo.CompStatusLeaving case "down": - return topo.ComponentStatusDown + return topo.CompStatusDown case "disconnected": - return topo.ComponentStatusUnreachable + return topo.CompStatusUnreachable default: - return topo.ComponentStatusUnreachable + return topo.CompStatusUnreachable } } diff --git a/util/topo/pdtopo/store_test.go b/util/topo/pdtopo/store_test.go index 26c81a6699..c655fbbfb2 100644 --- a/util/topo/pdtopo/store_test.go +++ b/util/topo/pdtopo/store_test.go @@ -14,7 +14,7 @@ import ( ) func TestGetStoreInstances(t *testing.T) { - apiClient := fixture.NewAPIAPIClientFixture() + apiClient := fixture.NewAPIClientFixture() tiKvStores, tiFlashStores, err := pdtopo.GetStoreInstances(context.Background(), apiClient) require.NoError(t, err) require.Equal(t, []topo.TiKVStoreInfo{ @@ -24,7 +24,7 @@ func TestGetStoreInstances(t *testing.T) { IP: "172.16.5.141", Port: 20160, DeployPath: "/home/tidb/tidb-deploy/tikv-20160/bin", - Status: topo.ComponentStatusUp, + Status: topo.CompStatusUp, StatusPort: 20180, Labels: map[string]string{}, StartTimestamp: 1636421301, @@ -35,7 +35,7 @@ func TestGetStoreInstances(t *testing.T) { IP: "172.16.5.218", Port: 20160, DeployPath: "/home/tidb/tidb-deploy/tikv-20160/bin", - Status: topo.ComponentStatusUp, + Status: topo.CompStatusUp, StatusPort: 20180, Labels: map[string]string{}, StartTimestamp: 1636421304, @@ -46,7 +46,7 @@ func TestGetStoreInstances(t *testing.T) { IP: "172.16.6.168", Port: 20160, DeployPath: "/home/tidb/tidb-deploy/tikv-20160/bin", - Status: topo.ComponentStatusUp, + Status: topo.CompStatusUp, StatusPort: 20180, Labels: map[string]string{}, StartTimestamp: 1636421304, diff --git a/util/topo/pdtopo/tidb.go b/util/topo/pdtopo/tidb.go index b19a25ee69..e9e23f05f1 100644 --- a/util/topo/pdtopo/tidb.go +++ b/util/topo/pdtopo/tidb.go @@ -81,7 +81,7 @@ func GetTiDBInstances(ctx context.Context, etcdClient *clientv3.Client) ([]topo. for addr, info := range nodesInfo { if _, ok := nodesAlive[addr]; ok { - info.Status = topo.ComponentStatusUp + info.Status = topo.CompStatusUp } nodes = append(nodes, *info) } @@ -123,7 +123,7 @@ func parseTiDBInfo(address string, value []byte) (*topo.TiDBInfo, error) { IP: hostname, Port: port, DeployPath: ds.DeployPath, - Status: topo.ComponentStatusUnreachable, + Status: topo.CompStatusUnreachable, StatusPort: ds.StatusPort, StartTimestamp: ds.StartTimestamp, }, nil diff --git a/util/topo/provider.go b/util/topo/provider.go index 3eb179ac6b..a662581f80 100644 --- a/util/topo/provider.go +++ b/util/topo/provider.go @@ -6,6 +6,7 @@ import ( "context" ) +// TopologyProvider provides the topology information for different components. type TopologyProvider interface { GetPD(ctx context.Context) ([]PDInfo, error) GetTiDB(ctx context.Context) ([]TiDBInfo, error) diff --git a/util/topo/provider_cached.go b/util/topo/provider_cached.go index df99716d8d..b100172ca0 100644 --- a/util/topo/provider_cached.go +++ b/util/topo/provider_cached.go @@ -19,7 +19,7 @@ type CachedTopology struct { var _ TopologyProvider = (*CachedTopology)(nil) -func NewCachedTopology(p TopologyProvider, ttl time.Duration) *CachedTopology { +func NewCachedTopology(p TopologyProvider, ttl time.Duration) TopologyProvider { cache := ttlcache.NewCache() cache.SkipTTLExtensionOnHit(true) _ = cache.SetTTL(ttl)