Skip to content

Commit

Permalink
config: validate dashboard-address (#2517) (#2522)
Browse files Browse the repository at this point in the history
Signed-off-by: Zheng Xiangsheng <hundundm@gmail.com>
  • Loading branch information
sre-bot committed Jun 15, 2020
1 parent 30f0b01 commit 85a49d5
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 10 deletions.
6 changes: 0 additions & 6 deletions pkg/dashboard/adapter/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package adapter

import (
"context"
"net/url"
"sort"
"sync"
"time"
Expand Down Expand Up @@ -137,11 +136,6 @@ func (m *Manager) checkAddress() {
m.stopService()
return
default:
if _, err := url.Parse(dashboardAddress); err != nil {
log.Error("illegal dashboard address", zap.String("address", dashboardAddress))
return
}

if m.isLeader && m.needResetAddress(dashboardAddress) {
m.setNewAddress()
return
Expand Down
2 changes: 1 addition & 1 deletion pkg/dashboard/adapter/redirector.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (h *Redirector) SetAddress(addr string) {

h.status.Start()
h.address = addr
target, _ := url.Parse(addr) // error has been handled in checkAddress
target, _ := url.Parse(addr) // error has been handled
h.proxy = httputil.NewSingleHostReverseProxy(target)

defaultDirector := h.proxy.Director
Expand Down
16 changes: 16 additions & 0 deletions server/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -1695,3 +1695,19 @@ func GetMembers(etcdClient *clientv3.Client) ([]*pdpb.Member, error) {

return members, nil
}

// IsClientURL returns whether addr is a ClientUrl of any member.
func IsClientURL(addr string, etcdClient *clientv3.Client) bool {
members, err := GetMembers(etcdClient)
if err != nil {
return false
}
for _, member := range members {
for _, u := range member.GetClientUrls() {
if u == addr {
return true
}
}
}
return false
}
18 changes: 16 additions & 2 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,10 +948,10 @@ func (c *PDServerConfig) adjust(meta *configMetaData) error {
if !meta.IsDefined("dashboard-address") {
c.DashboardAddress = defaultDashboardAddress
}
return nil
return c.Validate()
}

// Clone retruns a cloned PD server config.
// Clone returns a cloned PD server config.
func (c *PDServerConfig) Clone() *PDServerConfig {
runtimeServices := make(typeutil.StringSlice, len(c.RuntimeServices))
copy(runtimeServices, c.RuntimeServices)
Expand All @@ -965,6 +965,20 @@ func (c *PDServerConfig) Clone() *PDServerConfig {
}
}

// Validate is used to validate if some pd-server configurations are right.
func (c *PDServerConfig) Validate() error {
switch c.DashboardAddress {
case "auto":
case "none":
default:
if err := ValidateURLWithScheme(c.DashboardAddress); err != nil {
return err
}
}

return nil
}

// StoreLabel is the config item of LabelPropertyConfig.
type StoreLabel struct {
Key string `toml:"key" json:"key"`
Expand Down
65 changes: 65 additions & 0 deletions server/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,71 @@ func newTestScheduleOption() (*PersistOptions, error) {
return opt, nil
}

func (s *testConfigSuite) TestPDServerConfig(c *C) {
tests := []struct {
cfgData string
hasErr bool
dashboardAddress string
}{
{
`
[pd-server]
dashboard-address = "http://127.0.0.1:2379"
`,
false,
"http://127.0.0.1:2379",
},
{
`
[pd-server]
dashboard-address = "auto"
`,
false,
"auto",
},
{
`
[pd-server]
dashboard-address = "none"
`,
false,
"none",
},
{
"",
false,
"auto",
},
{
`
[pd-server]
dashboard-address = "127.0.0.1:2379"
`,
true,
"",
},
{
`
[pd-server]
dashboard-address = "foo"
`,
true,
"",
},
}

for _, t := range tests {
cfg := NewConfig()
meta, err := toml.Decode(t.cfgData, &cfg)
c.Assert(err, IsNil)
err = cfg.Adjust(&meta)
c.Assert(err != nil, Equals, t.hasErr)
if !t.hasErr {
c.Assert(cfg.PDServerCfg.DashboardAddress, Equals, t.dashboardAddress)
}
}
}

func (s *testConfigSuite) TestDashboardConfig(c *C) {
cfgData := `
[dashboard]
Expand Down
13 changes: 13 additions & 0 deletions server/config/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package config

import (
"net/url"
"regexp"

"github.com/pingcap/kvproto/pkg/metapb"
Expand Down Expand Up @@ -49,3 +50,15 @@ func ValidateLabels(labels []*metapb.StoreLabel) error {
}
return nil
}

// ValidateURLWithScheme checks the format of the URL.
func ValidateURLWithScheme(rawurl string) error {
u, err := url.ParseRequestURI(rawurl)
if err != nil {
return err
}
if u.Scheme == "" || u.Host == "" {
return errors.Errorf("%s has no scheme", rawurl)
}
return nil
}
24 changes: 23 additions & 1 deletion server/config/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var _ = Suite(&testUtilSuite{})

type testUtilSuite struct{}

func (s *testUtilSuite) TestVerifyLabels(c *C) {
func (s *testUtilSuite) TestValidateLabels(c *C) {
tests := []struct {
label string
hasErr bool
Expand Down Expand Up @@ -54,3 +54,25 @@ func (s *testUtilSuite) TestVerifyLabels(c *C) {
c.Assert(ValidateLabels([]*metapb.StoreLabel{{Key: t.label}}) != nil, Equals, t.hasErr)
}
}

func (s *testUtilSuite) TestValidateURLWithScheme(c *C) {
tests := []struct {
addr string
hasErr bool
}{
{"", true},
{"foo", true},
{"/foo", true},
{"http", true},
{"http://", true},
{"http://foo", false},
{"https://foo", false},
{"http://127.0.0.1", false},
{"http://127.0.0.1/", false},
{"https://foo.com/bar", false},
{"https://foo.com/bar/", false},
}
for _, t := range tests {
c.Assert(ValidateURLWithScheme(t.addr) != nil, Equals, t.hasErr)
}
}
23 changes: 23 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,14 @@ func (s *Server) GetAddr() string {
return s.cfg.AdvertiseClientUrls
}

// GetClientScheme returns the client URL scheme
func (s *Server) GetClientScheme() string {
if len(s.cfg.Security.CertPath) == 0 && len(s.cfg.Security.KeyPath) == 0 {
return "http"
}
return "https"
}

// GetMemberInfo returns the server member information.
func (s *Server) GetMemberInfo() *pdpb.Member {
return proto.Clone(s.member.Member()).(*pdpb.Member)
Expand Down Expand Up @@ -786,6 +794,21 @@ func (s *Server) GetPDServerConfig() *config.PDServerConfig {

// SetPDServerConfig sets the server config.
func (s *Server) SetPDServerConfig(cfg config.PDServerConfig) error {
switch cfg.DashboardAddress {
case "auto":
case "none":
default:
if !strings.HasPrefix(cfg.DashboardAddress, "http") {
cfg.DashboardAddress = fmt.Sprintf("%s://%s", s.GetClientScheme(), cfg.DashboardAddress)
}
if !cluster.IsClientURL(cfg.DashboardAddress, s.client) {
return errors.Errorf("%s is not the client url of any member", cfg.DashboardAddress)
}
}
if err := cfg.Validate(); err != nil {
return err
}

old := s.persistOptions.GetPDServerConfig()
s.persistOptions.SetPDServerConfig(&cfg)
if err := s.persistOptions.Persist(s.storage); err != nil {
Expand Down

0 comments on commit 85a49d5

Please sign in to comment.