From 24e64d4d01bf14284a0b46bacba264723474f417 Mon Sep 17 00:00:00 2001 From: lhy1024 Date: Wed, 10 Jan 2024 14:29:56 +0800 Subject: [PATCH] mcs: add option to control redirect http request Signed-off-by: lhy1024 --- pkg/utils/apiutil/serverapi/middleware.go | 3 + tests/integrations/mcs/scheduling/api_test.go | 25 +++++-- tools/pd-ctl/pdctl/command/config_command.go | 71 +++++++++++++++---- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/pkg/utils/apiutil/serverapi/middleware.go b/pkg/utils/apiutil/serverapi/middleware.go index c7979dcc0385..d328a65ae05c 100755 --- a/pkg/utils/apiutil/serverapi/middleware.go +++ b/pkg/utils/apiutil/serverapi/middleware.go @@ -119,6 +119,9 @@ func (h *redirector) matchMicroServiceRedirectRules(r *http.Request) (bool, stri if len(h.microserviceRedirectRules) == 0 { return false, "" } + if r.URL.Query().Get("redirect_mcs") == "false" { + return false, "" + } // Remove trailing '/' from the URL path // It will be helpful when matching the redirect rules "schedulers" or "schedulers/{name}" r.URL.Path = strings.TrimRight(r.URL.Path, "/") diff --git a/tests/integrations/mcs/scheduling/api_test.go b/tests/integrations/mcs/scheduling/api_test.go index 2572ae459d59..0efc95e616b7 100644 --- a/tests/integrations/mcs/scheduling/api_test.go +++ b/tests/integrations/mcs/scheduling/api_test.go @@ -19,6 +19,7 @@ import ( "github.com/tikv/pd/pkg/schedule/handler" "github.com/tikv/pd/pkg/schedule/labeler" "github.com/tikv/pd/pkg/schedule/placement" + "github.com/tikv/pd/pkg/slice" "github.com/tikv/pd/pkg/statistics" "github.com/tikv/pd/pkg/storage" "github.com/tikv/pd/pkg/utils/apiutil" @@ -109,17 +110,17 @@ func (suite *apiTestSuite) checkAPIForward(cluster *tests.TestCluster) { leader := cluster.GetLeaderServer().GetServer() urlPrefix := fmt.Sprintf("%s/pd/api/v1", leader.GetAddr()) - var slice []string + var respSlice []string var resp map[string]interface{} testutil.Eventually(re, func() bool { return leader.GetRaftCluster().IsServiceIndependent(utils.SchedulingServiceName) }) // Test operators - err := testutil.ReadGetJSON(re, testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "operators"), &slice, + err := testutil.ReadGetJSON(re, testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "operators"), &respSlice, testutil.WithHeader(re, apiutil.ForwardToMicroServiceHeader, "true")) re.NoError(err) - re.Empty(slice) + re.Empty(respSlice) err = testutil.CheckPostJSON(testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "operators"), []byte(``), testutil.StatusNotOK(re), testutil.WithHeader(re, apiutil.ForwardToMicroServiceHeader, "true")) @@ -167,10 +168,12 @@ func (suite *apiTestSuite) checkAPIForward(cluster *tests.TestCluster) { // Should not redirect: // "/schedulers", http.MethodPost // "/schedulers/{name}", http.MethodDelete - err = testutil.ReadGetJSON(re, testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "schedulers"), &slice, - testutil.WithHeader(re, apiutil.ForwardToMicroServiceHeader, "true")) - re.NoError(err) - re.Contains(slice, "balance-leader-scheduler") + testutil.Eventually(re, func() bool { + err = testutil.ReadGetJSON(re, testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "schedulers"), &respSlice, + testutil.WithHeader(re, apiutil.ForwardToMicroServiceHeader, "true")) + re.NoError(err) + return slice.Contains(respSlice, "balance-leader-scheduler") + }) postScheduler := func(delay int) { input := make(map[string]interface{}) @@ -361,6 +364,14 @@ func (suite *apiTestSuite) checkAPIForward(cluster *tests.TestCluster) { err = testutil.CheckPostJSON(testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "config/placement-rule/pd"), rulesArgs, testutil.WithoutHeader(re, apiutil.ForwardToMicroServiceHeader)) re.NoError(err) + + // test redirect is disabled + err = testutil.CheckGetJSON(testDialClient, fmt.Sprintf("%s/%s", urlPrefix, "config/placement-rule/pd"), nil, + testutil.WithHeader(re, apiutil.ForwardToMicroServiceHeader, "true")) + re.NoError(err) + err = testutil.CheckGetJSON(testDialClient, fmt.Sprintf("%s/%s?redirect_mcs=false", urlPrefix, "config/placement-rule/pd"), nil, + testutil.WithoutHeader(re, apiutil.ForwardToMicroServiceHeader)) + re.NoError(err) } func (suite *apiTestSuite) TestConfig() { diff --git a/tools/pd-ctl/pdctl/command/config_command.go b/tools/pd-ctl/pdctl/command/config_command.go index 2d0c3844995b..1d8ae5cf79a3 100644 --- a/tools/pd-ctl/pdctl/command/config_command.go +++ b/tools/pd-ctl/pdctl/command/config_command.go @@ -31,20 +31,21 @@ import ( "github.com/tikv/pd/server/config" ) -var ( - configPrefix = "pd/api/v1/config" - schedulePrefix = "pd/api/v1/config/schedule" - replicatePrefix = "pd/api/v1/config/replicate" - labelPropertyPrefix = "pd/api/v1/config/label-property" - clusterVersionPrefix = "pd/api/v1/config/cluster-version" - rulesPrefix = "pd/api/v1/config/rules" - rulesBatchPrefix = "pd/api/v1/config/rules/batch" - rulePrefix = "pd/api/v1/config/rule" - ruleGroupPrefix = "pd/api/v1/config/rule_group" - ruleGroupsPrefix = "pd/api/v1/config/rule_groups" - replicationModePrefix = "pd/api/v1/config/replication-mode" - ruleBundlePrefix = "pd/api/v1/config/placement-rule" - pdServerPrefix = "pd/api/v1/config/pd-server" +const ( + configPrefix = "pd/api/v1/config" + schedulePrefix = "pd/api/v1/config/schedule" + replicatePrefix = "pd/api/v1/config/replicate" + labelPropertyPrefix = "pd/api/v1/config/label-property" + clusterVersionPrefix = "pd/api/v1/config/cluster-version" + rulesPrefix = "pd/api/v1/config/rules" + rulesBatchPrefix = "pd/api/v1/config/rules/batch" + rulePrefix = "pd/api/v1/config/rule" + ruleGroupPrefix = "pd/api/v1/config/rule_group" + ruleGroupsPrefix = "pd/api/v1/config/rule_groups" + replicationModePrefix = "pd/api/v1/config/replication-mode" + ruleBundlePrefix = "pd/api/v1/config/placement-rule" + pdServerPrefix = "pd/api/v1/config/pd-server" + flagRedirectMicroService = "redirect_mcs" ) // NewConfigCommand return a config subcommand of rootCmd @@ -437,6 +438,7 @@ func NewPlacementRulesCommand() *cobra.Command { show.Flags().String("id", "", "rule id") show.Flags().String("region", "", "region id") show.Flags().Bool("detail", false, "detailed match info for region") + show.Flags().Bool(flagRedirectMicroService, true, "allow to redirect to micro service") load := &cobra.Command{ Use: "load", Short: "load placement rules to a file", @@ -446,6 +448,7 @@ func NewPlacementRulesCommand() *cobra.Command { load.Flags().String("id", "", "rule id") load.Flags().String("region", "", "region id") load.Flags().String("out", "rules.json", "the filename contains rules") + load.Flags().Bool(flagRedirectMicroService, true, "allow to redirect to micro service") save := &cobra.Command{ Use: "save", Short: "save rules from file", @@ -461,6 +464,7 @@ func NewPlacementRulesCommand() *cobra.Command { Short: "show rule group configuration(s)", Run: showRuleGroupFunc, } + ruleGroupShow.Flags().Bool(flagRedirectMicroService, true, "allow to redirect to micro service") ruleGroupSet := &cobra.Command{ Use: "set ", Short: "update rule group configuration", @@ -483,6 +487,7 @@ func NewPlacementRulesCommand() *cobra.Command { Run: getRuleBundle, } ruleBundleGet.Flags().String("out", "", "the output file") + ruleBundleGet.Flags().Bool(flagRedirectMicroService, true, "allow to redirect to micro service") ruleBundleSet := &cobra.Command{ Use: "set", Short: "set rule group config and its rules from file", @@ -501,6 +506,7 @@ func NewPlacementRulesCommand() *cobra.Command { Run: loadRuleBundle, } ruleBundleLoad.Flags().String("out", "rules.json", "the output file") + ruleBundleLoad.Flags().Bool(flagRedirectMicroService, true, "allow to redirect to micro service") ruleBundleSave := &cobra.Command{ Use: "save", Short: "save all group configs and rules from file", @@ -561,6 +567,15 @@ func getPlacementRulesFunc(cmd *cobra.Command, args []string) { cmd.Println(`"region" should not be specified with "group" or "id" at the same time`) return } + allowRedirectMicroService, err := cmd.Flags().GetBool(flagRedirectMicroService) + if err != nil { + cmd.PrintErrln("Failed to parse flag: ", err) + return + } + if !allowRedirectMicroService { + reqPath += "?redirect_mcs=false" + } + res, err := doRequest(cmd, reqPath, http.MethodGet, http.Header{}) if err != nil { cmd.Println(err) @@ -629,6 +644,14 @@ func showRuleGroupFunc(cmd *cobra.Command, args []string) { if len(args) > 0 { reqPath = path.Join(ruleGroupPrefix, args[0]) } + allowRedirectMicroService, err := cmd.Flags().GetBool(flagRedirectMicroService) + if err != nil { + cmd.PrintErrln("Failed to parse flag: ", err) + return + } + if !allowRedirectMicroService { + reqPath += "?redirect_mcs=false" + } res, err := doRequest(cmd, reqPath, http.MethodGet, http.Header{}) if err != nil { @@ -671,6 +694,14 @@ func getRuleBundle(cmd *cobra.Command, args []string) { } reqPath := path.Join(ruleBundlePrefix, args[0]) + allowRedirectMicroService, err := cmd.Flags().GetBool(flagRedirectMicroService) + if err != nil { + cmd.PrintErrln("Failed to parse flag: ", err) + return + } + if !allowRedirectMicroService { + reqPath += "?redirect_mcs=false" + } res, err := doRequest(cmd, reqPath, http.MethodGet, http.Header{}) if err != nil { @@ -747,7 +778,17 @@ func delRuleBundle(cmd *cobra.Command, args []string) { } func loadRuleBundle(cmd *cobra.Command, args []string) { - res, err := doRequest(cmd, ruleBundlePrefix, http.MethodGet, http.Header{}) + reqPath := ruleBundlePrefix + allowRedirectMicroService, err := cmd.Flags().GetBool(flagRedirectMicroService) + if err != nil { + cmd.PrintErrln("Failed to parse flag: ", err) + return + } + if !allowRedirectMicroService { + reqPath += "?redirect_mcs=false" + } + + res, err := doRequest(cmd, reqPath, http.MethodGet, http.Header{}) if err != nil { cmd.Println(err) return