Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config, api: Add Service Config #4869

Merged
merged 14 commits into from
May 17, 2022
32 changes: 32 additions & 0 deletions server/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func (h *confHandler) updateConfig(cfg *config.Config, key string, value interfa
return errors.Errorf("cannot update config prefix %s", kp[0])
}
return h.updateReplicationModeConfig(cfg, kp[1:], value)
case "service":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a better naming?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a better naming?

how about "self-protection"

return h.updateServiceConfig(cfg, kp[len(kp)-1], value)
case "pd-server":
return h.updatePDServerConfig(cfg, kp[len(kp)-1], value)
case "log":
Expand Down Expand Up @@ -250,6 +252,27 @@ func (h *confHandler) updateReplicationModeConfig(config *config.Config, key []s
return err
}

func (h *confHandler) updateServiceConfig(config *config.Config, key string, value interface{}) error {
data, err := json.Marshal(map[string]interface{}{key: value})
if err != nil {
return err
}

updated, found, err := mergeConfig(&config.ServiceCfg, data)
if err != nil {
return err
}

if !found {
return errors.Errorf("config item %s not found", key)
}

if updated {
err = h.svr.SetServiceConfig(config.ServiceCfg)
}
return err
}

func (h *confHandler) updatePDServerConfig(config *config.Config, key string, value interface{}) error {
data, err := json.Marshal(map[string]interface{}{key: value})
if err != nil {
Expand Down Expand Up @@ -535,6 +558,15 @@ func (h *confHandler) SetReplicationModeConfig(w http.ResponseWriter, r *http.Re
h.rd.JSON(w, http.StatusOK, "The replication mode config is updated.")
}

// @Tags config
// @Summary Get Service config.
// @Produce json
// @Success 200 {object} config.ServiceConfig
// @Router /config/service [get]
func (h *confHandler) GetServiceConfig(w http.ResponseWriter, r *http.Request) {
h.rd.JSON(w, http.StatusOK, h.svr.GetServiceConfig())
}

// @Tags config
// @Summary Get PD server config.
// @Produce json
Expand Down
49 changes: 28 additions & 21 deletions server/api/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,34 @@ func (s *testConfigSuite) TestConfigDefault(c *C) {
c.Assert(defaultCfg.PDServerCfg.MetricStorage, Equals, "")
}

func (s *testConfigSuite) TestConfigService(c *C) {
addrGet := fmt.Sprintf("%s/config/service", s.urlPrefix)
sc := &config.ServiceConfig{}
c.Assert(readJSON(testDialClient, addrGet, sc), IsNil)
c.Assert(sc.EnableAudit, Equals, false)

addrPost := fmt.Sprintf("%s/config", s.urlPrefix)
// test update enable-audit
ms := map[string]interface{}{
"enable-audit": "true",
}
postData, err := json.Marshal(ms)
c.Assert(err, IsNil)
c.Assert(postJSON(testDialClient, addrPost, postData), IsNil)
sc = &config.ServiceConfig{}
c.Assert(readJSON(testDialClient, addrGet, sc), IsNil)
c.Assert(sc.EnableAudit, Equals, true)
ms = map[string]interface{}{
"enable-audit": "false",
}
postData, err = json.Marshal(ms)
c.Assert(err, IsNil)
c.Assert(postJSON(testDialClient, addrPost, postData), IsNil)
sc = &config.ServiceConfig{}
c.Assert(readJSON(testDialClient, addrGet, sc), IsNil)
c.Assert(sc.EnableAudit, Equals, false)
}

func (s *testConfigSuite) TestConfigPDServer(c *C) {
addrPost := fmt.Sprintf("%s/config", s.urlPrefix)

Expand All @@ -301,27 +329,6 @@ func (s *testConfigSuite) TestConfigPDServer(c *C) {
c.Assert(sc.FlowRoundByDigit, Equals, int(3))
c.Assert(sc.MinResolvedTSPersistenceInterval, Equals, typeutil.NewDuration(0))
c.Assert(sc.MaxResetTSGap.Duration, Equals, 24*time.Hour)
c.Assert(sc.EnableAudit, Equals, false)

// test update enable-audit
ms = map[string]interface{}{
"enable-audit": true,
}
postData, err = json.Marshal(ms)
c.Assert(err, IsNil)
c.Assert(postJSON(testDialClient, addrPost, postData), IsNil)
sc = &config.PDServerConfig{}
c.Assert(readJSON(testDialClient, addrGet, sc), IsNil)
c.Assert(sc.EnableAudit, Equals, true)
ms = map[string]interface{}{
"enable-audit": false,
}
postData, err = json.Marshal(ms)
c.Assert(err, IsNil)
c.Assert(postJSON(testDialClient, addrPost, postData), IsNil)
sc = &config.PDServerConfig{}
c.Assert(readJSON(testDialClient, addrGet, sc), IsNil)
c.Assert(sc.EnableAudit, Equals, false)
}

var ttlConfig = map[string]interface{}{
Expand Down
1 change: 1 addition & 0 deletions server/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func createRouter(prefix string, svr *server.Server) *mux.Router {
registerFunc(apiRouter, "/config/default", confHandler.GetDefaultConfig, setMethods("GET"))
registerFunc(apiRouter, "/config/schedule", confHandler.GetScheduleConfig, setMethods("GET"))
registerFunc(apiRouter, "/config/schedule", confHandler.SetScheduleConfig, setMethods("POST"), setAuditBackend(localLog))
registerFunc(apiRouter, "/config/service", confHandler.GetServiceConfig, setMethods("GET"))
registerFunc(apiRouter, "/config/pd-server", confHandler.GetPDServerConfig, setMethods("GET"))
registerFunc(apiRouter, "/config/replicate", confHandler.GetReplicationConfig, setMethods("GET"))
registerFunc(apiRouter, "/config/replicate", confHandler.SetReplicationConfig, setMethods("POST"), setAuditBackend(localLog))
Expand Down
30 changes: 25 additions & 5 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ type Config struct {

Replication ReplicationConfig `toml:"replication" json:"replication"`

ServiceCfg ServiceConfig `toml:"service" json:"service"`

PDServerCfg PDServerConfig `toml:"pd-server" json:"pd-server"`

ClusterVersion semver.Version `toml:"cluster-version" json:"cluster-version"`
Expand Down Expand Up @@ -574,6 +576,10 @@ func (c *Config) Adjust(meta *toml.MetaData, reloading bool) error {
return err
}

if err := c.ServiceCfg.adjust(configMetaData.Child("service")); err != nil {
return err
}

if err := c.PDServerCfg.adjust(configMetaData.Child("pd-server")); err != nil {
return err
}
Expand Down Expand Up @@ -1086,6 +1092,25 @@ func (c *ReplicationConfig) adjust(meta *configMetaData) error {
return c.Validate()
}

// ServiceConfig is the configuration for PD service such as HTTP API and gRPC.
type ServiceConfig struct {
// EnableAudit controls the switch of the audit middleware
EnableAudit bool `toml:"enable-audit" json:"enable-audit,string"`
}

// Clone returns a cloned PD server config.
func (c *ServiceConfig) Clone() *ServiceConfig {
cfg := *c
return &cfg
}

func (c *ServiceConfig) adjust(meta *configMetaData) error {
if !meta.IsDefined("enable-audit") {
c.EnableAudit = defaultEnableAuditMiddleware
}
return nil
}

// PDServerConfig is the configuration for pd server.
// NOTE: This type is exported by HTTP API. Please pay more attention when modifying it.
type PDServerConfig struct {
Expand All @@ -1110,8 +1135,6 @@ type PDServerConfig struct {
FlowRoundByDigit int `toml:"flow-round-by-digit" json:"flow-round-by-digit"`
// MinResolvedTSPersistenceInterval is the interval to save the min resolved ts.
MinResolvedTSPersistenceInterval typeutil.Duration `toml:"min-resolved-ts-persistence-interval" json:"min-resolved-ts-persistence-interval"`
// EnableAudit controls the switch of the audit middleware
EnableAudit bool `toml:"enable-audit" json:"enable-audit"`
}

func (c *PDServerConfig) adjust(meta *configMetaData) error {
Expand All @@ -1137,9 +1160,6 @@ func (c *PDServerConfig) adjust(meta *configMetaData) error {
if !meta.IsDefined("min-resolved-ts-persistence-interval") {
adjustDuration(&c.MinResolvedTSPersistenceInterval, defaultMinResolvedTSPersistenceInterval)
}
if !meta.IsDefined("enable-audit") {
c.EnableAudit = defaultEnableAuditMiddleware
}
c.migrateConfigurationFromFile(meta)
return c.Validate()
}
Expand Down
4 changes: 4 additions & 0 deletions server/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,10 @@ func (s *testConfigSuite) TestConfigClone(c *C) {
replication.adjust(emptyConfigMetaData)
c.Assert(replication.Clone(), DeepEquals, replication)

service := &ServiceConfig{}
service.adjust(emptyConfigMetaData)
c.Assert(service.Clone(), DeepEquals, service)

pdServer := &PDServerConfig{}
pdServer.adjust(emptyConfigMetaData)
c.Assert(pdServer.Clone(), DeepEquals, pdServer)
Expand Down
16 changes: 15 additions & 1 deletion server/config/persist_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type PersistOptions struct {
ttl *cache.TTLString
schedule atomic.Value
replication atomic.Value
serviceConfig atomic.Value
pdServerConfig atomic.Value
replicationMode atomic.Value
labelProperty atomic.Value
Expand All @@ -57,6 +58,7 @@ func NewPersistOptions(cfg *Config) *PersistOptions {
o := &PersistOptions{}
o.schedule.Store(&cfg.Schedule)
o.replication.Store(&cfg.Replication)
o.serviceConfig.Store(&cfg.ServiceCfg)
o.pdServerConfig.Store(&cfg.PDServerCfg)
o.replicationMode.Store(&cfg.ReplicationMode)
o.labelProperty.Store(cfg.LabelProperty)
Expand Down Expand Up @@ -85,6 +87,16 @@ func (o *PersistOptions) SetReplicationConfig(cfg *ReplicationConfig) {
o.replication.Store(cfg)
}

// GetServiceConfig returns pd server configurations.
func (o *PersistOptions) GetServiceConfig() *ServiceConfig {
return o.serviceConfig.Load().(*ServiceConfig)
}

// SetServiceConfig sets the PD configuration.
func (o *PersistOptions) SetServiceConfig(cfg *ServiceConfig) {
o.serviceConfig.Store(cfg)
}

// GetPDServerConfig returns pd server configurations.
func (o *PersistOptions) GetPDServerConfig() *PDServerConfig {
return o.pdServerConfig.Load().(*PDServerConfig)
Expand Down Expand Up @@ -446,7 +458,7 @@ func (o *PersistOptions) GetLeaderSchedulePolicy() core.SchedulePolicy {

// IsAuditEnabled returns whether audit middleware is enabled
func (o *PersistOptions) IsAuditEnabled() bool {
return o.GetPDServerConfig().EnableAudit
return o.GetServiceConfig().EnableAudit
}

// GetKeyType is to get key type.
Expand Down Expand Up @@ -598,6 +610,7 @@ func (o *PersistOptions) Persist(storage endpoint.ConfigStorage) error {
cfg := &Config{
Schedule: *o.GetScheduleConfig(),
Replication: *o.GetReplicationConfig(),
ServiceCfg: *o.GetServiceConfig(),
PDServerCfg: *o.GetPDServerConfig(),
ReplicationMode: *o.GetReplicationModeConfig(),
LabelProperty: o.GetLabelPropertyConfig(),
Expand Down Expand Up @@ -625,6 +638,7 @@ func (o *PersistOptions) Reload(storage endpoint.ConfigStorage) error {
if isExist {
o.schedule.Store(&cfg.Schedule)
o.replication.Store(&cfg.Replication)
o.serviceConfig.Store(&cfg.ServiceCfg)
o.pdServerConfig.Store(&cfg.PDServerCfg)
o.replicationMode.Store(&cfg.ReplicationMode)
o.labelProperty.Store(cfg.LabelProperty)
Expand Down
22 changes: 22 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ func (s *Server) GetConfig() *config.Config {
cfg := s.cfg.Clone()
cfg.Schedule = *s.persistOptions.GetScheduleConfig().Clone()
cfg.Replication = *s.persistOptions.GetReplicationConfig().Clone()
cfg.ServiceCfg = *s.persistOptions.GetServiceConfig().Clone()
cfg.PDServerCfg = *s.persistOptions.GetPDServerConfig().Clone()
cfg.ReplicationMode = *s.persistOptions.GetReplicationModeConfig()
cfg.LabelProperty = s.persistOptions.GetLabelPropertyConfig().Clone()
Expand Down Expand Up @@ -955,6 +956,27 @@ func (s *Server) SetReplicationConfig(cfg config.ReplicationConfig) error {
return nil
}

// GetServiceConfig gets the service config information.
func (s *Server) GetServiceConfig() *config.ServiceConfig {
return s.persistOptions.GetServiceConfig().Clone()
}

// SetServiceConfig sets the service config.
func (s *Server) SetServiceConfig(cfg config.ServiceConfig) error {
old := s.persistOptions.GetServiceConfig()
s.persistOptions.SetServiceConfig(&cfg)
if err := s.persistOptions.Persist(s.storage); err != nil {
s.persistOptions.SetServiceConfig(old)
log.Error("failed to update Service config",
zap.Reflect("new", cfg),
zap.Reflect("old", old),
errs.ZapError(err))
return err
}
log.Info("Service config is updated", zap.Reflect("new", cfg), zap.Reflect("old", old))
return nil
}

// GetPDServerConfig gets the balance config information.
func (s *Server) GetPDServerConfig() *config.PDServerConfig {
return s.persistOptions.GetPDServerConfig().Clone()
Expand Down
18 changes: 9 additions & 9 deletions tests/server/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func (s *testMiddlewareSuite) TestRequestInfoMiddleware(c *C) {
leader := s.cluster.GetServer(s.cluster.GetLeader())

input := map[string]interface{}{
"enable-audit": true,
"enable-audit": "true",
}
data, err := json.Marshal(input)
c.Assert(err, IsNil)
Expand Down Expand Up @@ -181,7 +181,7 @@ func (s *testMiddlewareSuite) TestRequestInfoMiddleware(c *C) {
c.Assert(resp.Header.Get("ip"), Equals, "127.0.0.1")

input = map[string]interface{}{
"enable-audit": false,
"enable-audit": "false",
}
data, err = json.Marshal(input)
c.Assert(err, IsNil)
Expand All @@ -206,7 +206,7 @@ func BenchmarkDoRequestWithServiceMiddleware(b *testing.B) {
cluster.WaitLeader()
leader := cluster.GetServer(cluster.GetLeader())
input := map[string]interface{}{
"enable-audit": true,
"enable-audit": "true",
}
data, _ := json.Marshal(input)
req, _ := http.NewRequest("POST", leader.GetAddr()+"/pd/api/v1/config", bytes.NewBuffer(data))
Expand All @@ -229,7 +229,7 @@ func BenchmarkDoRequestWithoutServiceMiddleware(b *testing.B) {
cluster.WaitLeader()
leader := cluster.GetServer(cluster.GetLeader())
input := map[string]interface{}{
"enable-audit": false,
"enable-audit": "false",
}
data, _ := json.Marshal(input)
req, _ := http.NewRequest("POST", leader.GetAddr()+"/pd/api/v1/config", bytes.NewBuffer(data))
Expand All @@ -254,7 +254,7 @@ func doTestRequest(srv *tests.TestServer) {
func (s *testMiddlewareSuite) TestAuditPrometheusBackend(c *C) {
leader := s.cluster.GetServer(s.cluster.GetLeader())
input := map[string]interface{}{
"enable-audit": true,
"enable-audit": "true",
}
data, err := json.Marshal(input)
c.Assert(err, IsNil)
Expand Down Expand Up @@ -302,7 +302,7 @@ func (s *testMiddlewareSuite) TestAuditPrometheusBackend(c *C) {
c.Assert(strings.Contains(output, "pd_service_audit_handling_seconds_count{component=\"anonymous\",method=\"HTTP\",service=\"GetTrend\"} 2"), Equals, true)

input = map[string]interface{}{
"enable-audit": false,
"enable-audit": "false",
}
data, err = json.Marshal(input)
c.Assert(err, IsNil)
Expand All @@ -322,7 +322,7 @@ func (s *testMiddlewareSuite) TestAuditLocalLogBackend(c *C) {
log.ReplaceGlobals(lg, p)
leader := s.cluster.GetServer(s.cluster.GetLeader())
input := map[string]interface{}{
"enable-audit": true,
"enable-audit": "true",
}
data, err := json.Marshal(input)
c.Assert(err, IsNil)
Expand Down Expand Up @@ -354,7 +354,7 @@ func BenchmarkDoRequestWithLocalLogAudit(b *testing.B) {
cluster.WaitLeader()
leader := cluster.GetServer(cluster.GetLeader())
input := map[string]interface{}{
"enable-audit": true,
"enable-audit": "true",
}
data, _ := json.Marshal(input)
req, _ := http.NewRequest("POST", leader.GetAddr()+"/pd/api/v1/config", bytes.NewBuffer(data))
Expand All @@ -377,7 +377,7 @@ func BenchmarkDoRequestWithoutLocalLogAudit(b *testing.B) {
cluster.WaitLeader()
leader := cluster.GetServer(cluster.GetLeader())
input := map[string]interface{}{
"enable-audit": false,
"enable-audit": "false",
}
data, _ := json.Marshal(input)
req, _ := http.NewRequest("POST", leader.GetAddr()+"/pd/api/v1/config", bytes.NewBuffer(data))
Expand Down