Skip to content

Commit

Permalink
dashboard: support internal proxy (#2508) (#2511)
Browse files Browse the repository at this point in the history
Signed-off-by: Zheng Xiangsheng <hundundm@gmail.com>
  • Loading branch information
sre-bot authored Jun 5, 2020
1 parent b9cb120 commit bbf1354
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 18 deletions.
4 changes: 4 additions & 0 deletions conf/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,7 @@ location-labels = []
## is running behind a reverse proxy. Do not configure it if you access
## Dashboard directly.
# public-path-prefix = "/dashboard"

## When enabled, request will be proxied to the instance running Dashboard
## internally instead of result in a 307 redirection.
# internal-proxy = false
12 changes: 12 additions & 0 deletions pkg/dashboard/adapter/redirector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"sync"

"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver"
"github.com/pingcap-incubator/tidb-dashboard/pkg/utils"
)

const (
Expand All @@ -36,13 +37,17 @@ type Redirector struct {

address string
proxy *httputil.ReverseProxy
// The status of the dashboard in the cluster.
// It is not equal to `apiserver.Service.status`.
status *utils.ServiceStatus
}

// NewRedirector creates a new Redirector.
func NewRedirector(name string, tlsConfig *tls.Config) *Redirector {
return &Redirector{
name: name,
tlsConfig: tlsConfig,
status: utils.NewServiceStatus(),
}
}

Expand All @@ -56,11 +61,13 @@ func (h *Redirector) SetAddress(addr string) {
}

if addr == "" {
h.status.Stop()
h.address = ""
h.proxy = nil
return
}

h.status.Start()
h.address = addr
target, _ := url.Parse(addr) // error has been handled in checkAddress
h.proxy = httputil.NewSingleHostReverseProxy(target)
Expand Down Expand Up @@ -117,3 +124,8 @@ func (h *Redirector) ReverseProxy(w http.ResponseWriter, r *http.Request) {

proxy.ServeHTTP(w, r)
}

// NewStatusAwareHandler returns a Handler that switches between different Handlers based on status.
func (h *Redirector) NewStatusAwareHandler(handler http.Handler) http.Handler {
return h.status.NewStatusAwareHandler(handler, apiserver.StoppedHandler)
}
34 changes: 24 additions & 10 deletions pkg/dashboard/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,34 @@ func SetCheckInterval(d time.Duration) {
// GetServiceBuilders returns all ServiceBuilders required by Dashboard
func GetServiceBuilders() []server.HandlerBuilder {
var (
err error
cfg *config.Config
redirector *adapter.Redirector
assets http.FileSystem
s *apiserver.Service
err error
cfg *config.Config
internalProxy bool
redirector *adapter.Redirector
assets http.FileSystem
s *apiserver.Service
)

// The order of execution must be sequential.
return []server.HandlerBuilder{
// Dashboard API Service
func(ctx context.Context, srv *server.Server) (http.Handler, server.ServiceGroup, error) {
if cfg, err = adapter.GenDashboardConfig(srv); err != nil {
return nil, apiServiceGroup, err
}
internalProxy = srv.GetConfig().Dashboard.InternalProxy
redirector = adapter.NewRedirector(srv.Name(), cfg.ClusterTLSConfig)
assets = ui.Assets(cfg)

var stoppedHandler http.Handler
if internalProxy {
stoppedHandler = http.HandlerFunc(redirector.ReverseProxy)
} else {
stoppedHandler = http.HandlerFunc(redirector.TemporaryRedirect)
}
s = apiserver.NewService(
cfg,
http.HandlerFunc(redirector.ReverseProxy),
stoppedHandler,
assets,
adapter.GenPDDataProviderConstructor(srv),
)
Expand All @@ -87,10 +97,14 @@ func GetServiceBuilders() []server.HandlerBuilder {
return nil, uiServiceGroup, err
}

handler := s.NewStatusAwareHandler(
http.StripPrefix(uiServiceGroup.PathPrefix, uiserver.Handler(assets)),
http.HandlerFunc(redirector.TemporaryRedirect),
)
var handler http.Handler
uiHandler := http.StripPrefix(uiServiceGroup.PathPrefix, uiserver.Handler(assets))
if internalProxy {
handler = redirector.NewStatusAwareHandler(uiHandler)
} else {
handler = s.NewStatusAwareHandler(uiHandler, http.HandlerFunc(redirector.TemporaryRedirect))
}

return handler, uiServiceGroup, nil
},
}
Expand Down
1 change: 1 addition & 0 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,7 @@ type DashboardConfig struct {
TiDBCertPath string `toml:"tidb-cert-path" json:"tidb_cert_path"`
TiDBKeyPath string `toml:"tidb-key-path" json:"tidb_key_path"`
PublicPathPrefix string `toml:"public-path-prefix" json:"public_path_prefix"`
InternalProxy bool `toml:"internal-proxy" json:"internal_proxy"`
}

// ToTiDBTLSConfig generates tls config for connecting to TiDB, used by tidb-dashboard.
Expand Down
29 changes: 21 additions & 8 deletions tests/dashboard/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/pingcap/pd/v4/pkg/dashboard"
"github.com/pingcap/pd/v4/pkg/testutil"
"github.com/pingcap/pd/v4/server"
"github.com/pingcap/pd/v4/server/config"
"github.com/pingcap/pd/v4/tests"
"github.com/pingcap/pd/v4/tests/pdctl"

Expand Down Expand Up @@ -72,6 +73,14 @@ func (s *serverTestSuite) TearDownSuite(c *C) {
dashboard.SetCheckInterval(time.Second)
}

func (s *serverTestSuite) TestDashboardRedirect(c *C) {
s.testDashboard(c, false)
}

func (s *serverTestSuite) TestDashboardProxy(c *C) {
s.testDashboard(c, true)
}

func (s *serverTestSuite) checkRespCode(c *C, url string, code int) {
resp, err := s.httpClient.Get(url) //nolint:gosec
c.Assert(err, IsNil)
Expand All @@ -85,20 +94,22 @@ func (s *serverTestSuite) waitForConfigSync() {
time.Sleep(time.Second)
}

func (s *serverTestSuite) checkServiceIsStarted(c *C, servers map[string]*tests.TestServer, leader *tests.TestServer) string {
func (s *serverTestSuite) checkServiceIsStarted(c *C, internalProxy bool, servers map[string]*tests.TestServer, leader *tests.TestServer) string {
s.waitForConfigSync()
dashboardAddress := leader.GetServer().GetPersistOptions().GetDashboardAddress()
hasServiceNode := false
for _, srv := range servers {
c.Assert(srv.GetPersistOptions().GetDashboardAddress(), Equals, dashboardAddress)
addr := srv.GetAddr()
if addr == dashboardAddress {
if addr == dashboardAddress || internalProxy {
s.checkRespCode(c, fmt.Sprintf("%s/dashboard/", addr), http.StatusOK)
s.checkRespCode(c, fmt.Sprintf("%s/dashboard/api/keyvisual/heatmaps", addr), http.StatusUnauthorized)
hasServiceNode = true
if addr == dashboardAddress {
hasServiceNode = true
}
} else {
s.checkRespCode(c, fmt.Sprintf("%s/dashboard/", addr), http.StatusTemporaryRedirect)
s.checkRespCode(c, fmt.Sprintf("%s/dashboard/api/keyvisual/heatmaps", addr), http.StatusUnauthorized)
s.checkRespCode(c, fmt.Sprintf("%s/dashboard/api/keyvisual/heatmaps", addr), http.StatusTemporaryRedirect)
}
}
c.Assert(hasServiceNode, IsTrue)
Expand All @@ -115,8 +126,10 @@ func (s *serverTestSuite) checkServiceIsStopped(c *C, servers map[string]*tests.
}
}

func (s *serverTestSuite) TestDashboard(c *C) {
cluster, err := tests.NewTestCluster(s.ctx, 3)
func (s *serverTestSuite) testDashboard(c *C, internalProxy bool) {
cluster, err := tests.NewTestCluster(s.ctx, 3, func(conf *config.Config) {
conf.Dashboard.InternalProxy = internalProxy
})
c.Assert(err, IsNil)
defer cluster.Destroy()
err = cluster.RunInitialServers()
Expand All @@ -130,7 +143,7 @@ func (s *serverTestSuite) TestDashboard(c *C) {
leaderAddr := leader.GetAddr()

// auto select node
dashboardAddress1 := s.checkServiceIsStarted(c, servers, leader)
dashboardAddress1 := s.checkServiceIsStarted(c, internalProxy, servers, leader)

// pd-ctl set another addr
var dashboardAddress2 string
Expand All @@ -143,7 +156,7 @@ func (s *serverTestSuite) TestDashboard(c *C) {
args := []string{"-u", leaderAddr, "config", "set", "dashboard-address", dashboardAddress2}
_, _, err = pdctl.ExecuteCommandC(cmd, args...)
c.Assert(err, IsNil)
s.checkServiceIsStarted(c, servers, leader)
s.checkServiceIsStarted(c, internalProxy, servers, leader)
c.Assert(leader.GetServer().GetPersistOptions().GetDashboardAddress(), Equals, dashboardAddress2)

// pd-ctl set stop
Expand Down

0 comments on commit bbf1354

Please sign in to comment.