Skip to content

Commit

Permalink
ctl: replace doRequest with HTTP client to get health status (#8212)
Browse files Browse the repository at this point in the history
ref #7300

Signed-off-by: okJiang <819421878@qq.com>
  • Loading branch information
okJiang authored May 27, 2024
1 parent 7cc3b4e commit dd7f2a7
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 21 deletions.
1 change: 1 addition & 0 deletions client/http/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const (
membersPrefix = "/pd/api/v1/members"
leaderPrefix = "/pd/api/v1/leader"
transferLeader = "/pd/api/v1/leader/transfer"
health = "/pd/api/v1/health"
// Config
Config = "/pd/api/v1/config"
ClusterVersion = "/pd/api/v1/config/cluster-version"
Expand Down
15 changes: 15 additions & 0 deletions client/http/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Client interface {
GetStores(context.Context) (*StoresInfo, error)
GetStore(context.Context, uint64) (*StoreInfo, error)
SetStoreLabels(context.Context, int64, map[string]string) error
GetHealthStatus(context.Context) ([]Health, error)
/* Config-related interfaces */
GetConfig(context.Context) (map[string]any, error)
SetConfig(context.Context, map[string]any, ...float64) error
Expand Down Expand Up @@ -337,6 +338,20 @@ func (c *client) SetStoreLabels(ctx context.Context, storeID int64, storeLabels
WithBody(jsonInput))
}

// GetHealthStatus gets the health status of the cluster.
func (c *client) GetHealthStatus(ctx context.Context) ([]Health, error) {
var healths []Health
err := c.request(ctx, newRequestInfo().
WithName(getHealthStatusName).
WithURI(health).
WithMethod(http.MethodGet).
WithResp(&healths))
if err != nil {
return nil, err
}
return healths, nil
}

// GetConfig gets the configurations.
func (c *client) GetConfig(ctx context.Context) (map[string]any, error) {
var config map[string]any
Expand Down
1 change: 1 addition & 0 deletions client/http/request_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
getStoresName = "GetStores"
getStoreName = "GetStore"
setStoreLabelsName = "SetStoreLabels"
getHealthStatusName = "GetHealthStatus"
getConfigName = "GetConfig"
setConfigName = "SetConfig"
getScheduleConfigName = "GetScheduleConfig"
Expand Down
9 changes: 9 additions & 0 deletions client/http/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,3 +661,12 @@ func stringToKeyspaceState(str string) (keyspacepb.KeyspaceState, error) {
return keyspacepb.KeyspaceState(0), fmt.Errorf("invalid KeyspaceState string: %s", str)
}
}

// Health reflects the cluster's health.
// NOTE: This type is moved from `server/api/health.go`, maybe move them to the same place later.
type Health struct {
Name string `json:"name"`
MemberID uint64 `json:"member_id"`
ClientUrls []string `json:"client_urls"`
Health bool `json:"health"`
}
1 change: 1 addition & 0 deletions pkg/dashboard/uiserver/embedded_assets_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
var once sync.Once

// Assets returns the Assets FileSystem of the dashboard UI
// NOTE: if you see "undefined: assets" error, please run `make dashboard-ui` in the root directory of the repository.
func Assets(cfg *config.Config) http.FileSystem {
once.Do(func() {
resPath := distroutil.MustGetResPath()
Expand Down
19 changes: 19 additions & 0 deletions tests/integrations/client/http_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,3 +811,22 @@ func (suite *httpClientTestSuite) checkUpdateKeyspaceGCManagementType(mode mode,
re.True(ok)
re.Equal(expectGCManagementType, val)
}

func (suite *httpClientTestSuite) TestGetHealthStatus() {
suite.RunTestInTwoModes(suite.checkGetHealthStatus)
}

func (suite *httpClientTestSuite) checkGetHealthStatus(mode mode, client pd.Client) {
re := suite.Require()
env := suite.env[mode]

healths, err := client.GetHealthStatus(env.ctx)
re.NoError(err)
re.Len(healths, 2)
sort.Slice(healths, func(i, j int) bool {
return healths[i].Name < healths[j].Name
})
re.Equal("pd1", healths[0].Name)
re.Equal("pd2", healths[1].Name)
re.True(healths[0].Health && healths[1].Health)
}
17 changes: 6 additions & 11 deletions tools/pd-ctl/pdctl/command/health_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,25 @@
package command

import (
"net/http"

"github.com/spf13/cobra"
)

var (
healthPrefix = "pd/api/v1/health"
)

// NewHealthCommand return a health subcommand of rootCmd
func NewHealthCommand() *cobra.Command {
m := &cobra.Command{
Use: "health",
Short: "show all node's health information of the pd cluster",
Run: showHealthCommandFunc,
Use: "health",
Short: "show all node's health information of the PD cluster",
PersistentPreRunE: requirePDClient,
Run: showHealthCommandFunc,
}
return m
}

func showHealthCommandFunc(cmd *cobra.Command, _ []string) {
r, err := doRequest(cmd, healthPrefix, http.MethodGet, http.Header{})
health, err := PDCli.GetHealthStatus(cmd.Context())
if err != nil {
cmd.Println(err)
return
}
cmd.Println(r)
jsonPrint(cmd, health)
}
10 changes: 0 additions & 10 deletions tools/pd-ctl/tests/global_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ func TestSendAndGetComponent(t *testing.T) {
})
// check http client api
// TODO: remove this comment after replacing dialClient with the PD HTTP client completely.
mux.HandleFunc("/pd/api/v1/health", func(w http.ResponseWriter, r *http.Request) {
callerID := apiutil.GetCallerIDOnHTTP(r)
re.Equal(command.PDControlCallerID, callerID)
fmt.Fprint(w, callerID)
})
mux.HandleFunc("/pd/api/v1/stores", func(w http.ResponseWriter, r *http.Request) {
callerID := apiutil.GetCallerIDOnHTTP(r)
re.Equal(command.PDControlCallerID, callerID)
Expand Down Expand Up @@ -82,11 +77,6 @@ func TestSendAndGetComponent(t *testing.T) {
"id": 1
}`), string(output))

args = []string{"-u", pdAddr, "health"}
output, err = ExecuteCommand(cmd, args...)
re.NoError(err)
re.Equal(fmt.Sprintf("%s\n", command.PDControlCallerID), string(output))

args = []string{"-u", pdAddr, "store"}
output, err = ExecuteCommand(cmd, args...)
re.NoError(err)
Expand Down

0 comments on commit dd7f2a7

Please sign in to comment.