mirror of https://github.com/status-im/consul.git
feat: add reporting config with reload (#16890)
This commit is contained in:
parent
37569837a2
commit
8255cc97f5
|
@ -1499,7 +1499,10 @@ func newConsulConfig(runtimeCfg *config.RuntimeConfig, logger hclog.Logger) (*co
|
||||||
cfg.RequestLimitsWriteRate = runtimeCfg.RequestLimitsWriteRate
|
cfg.RequestLimitsWriteRate = runtimeCfg.RequestLimitsWriteRate
|
||||||
cfg.Locality = runtimeCfg.StructLocality()
|
cfg.Locality = runtimeCfg.StructLocality()
|
||||||
|
|
||||||
|
cfg.Reporting.License.Enabled = runtimeCfg.Reporting.License.Enabled
|
||||||
|
|
||||||
enterpriseConsulConfig(cfg, runtimeCfg)
|
enterpriseConsulConfig(cfg, runtimeCfg)
|
||||||
|
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4187,6 +4190,11 @@ func (a *Agent) reloadConfigInternal(newCfg *config.RuntimeConfig) error {
|
||||||
HeartbeatTimeout: newCfg.ConsulRaftHeartbeatTimeout,
|
HeartbeatTimeout: newCfg.ConsulRaftHeartbeatTimeout,
|
||||||
ElectionTimeout: newCfg.ConsulRaftElectionTimeout,
|
ElectionTimeout: newCfg.ConsulRaftElectionTimeout,
|
||||||
RaftTrailingLogs: newCfg.RaftTrailingLogs,
|
RaftTrailingLogs: newCfg.RaftTrailingLogs,
|
||||||
|
Reporting: consul.Reporting{
|
||||||
|
License: consul.License{
|
||||||
|
Enabled: newCfg.Reporting.License.Enabled,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if err := a.delegate.ReloadConfig(cc); err != nil {
|
if err := a.delegate.ReloadConfig(cc); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
//go:build !consulent
|
||||||
|
// +build !consulent
|
||||||
|
|
||||||
|
package agent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAgent_consulConfig_Reporting(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("too slow for testing.Short")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
hcl := `
|
||||||
|
reporting {
|
||||||
|
license {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
a := NewTestAgent(t, hcl)
|
||||||
|
defer a.Shutdown()
|
||||||
|
require.Equal(t, false, a.consulConfig().Reporting.License.Enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAgent_consulConfig_Reporting_Default(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("too slow for testing.Short")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
hcl := `
|
||||||
|
reporting {
|
||||||
|
}
|
||||||
|
`
|
||||||
|
a := NewTestAgent(t, hcl)
|
||||||
|
defer a.Shutdown()
|
||||||
|
require.Equal(t, false, a.consulConfig().Reporting.License.Enabled)
|
||||||
|
}
|
|
@ -60,6 +60,10 @@ func validateEnterpriseConfigKeys(config *Config) []error {
|
||||||
add("license_path")
|
add("license_path")
|
||||||
config.LicensePath = nil
|
config.LicensePath = nil
|
||||||
}
|
}
|
||||||
|
if config.Reporting.License.Enabled != nil {
|
||||||
|
add("reporting.license.enabled")
|
||||||
|
config.Reporting.License.Enabled = nil
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,19 @@ func TestValidateEnterpriseConfigKeys(t *testing.T) {
|
||||||
require.Empty(t, c.LicensePath)
|
require.Empty(t, c.LicensePath)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"reporting.license.enabled": {
|
||||||
|
config: Config{
|
||||||
|
Reporting: Reporting{
|
||||||
|
License: License{
|
||||||
|
Enabled: &boolVal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
badKeys: []string{"reporting.license.enabled"},
|
||||||
|
check: func(t *testing.T, c *Config) {
|
||||||
|
require.Nil(t, c.Reporting.License.Enabled)
|
||||||
|
},
|
||||||
|
},
|
||||||
"multi": {
|
"multi": {
|
||||||
config: Config{
|
config: Config{
|
||||||
ReadReplica: &boolVal,
|
ReadReplica: &boolVal,
|
||||||
|
|
|
@ -295,6 +295,9 @@ type Config struct {
|
||||||
LicensePollMaxTime *string `mapstructure:"license_poll_max_time" json:"-"`
|
LicensePollMaxTime *string `mapstructure:"license_poll_max_time" json:"-"`
|
||||||
LicenseUpdateBaseTime *string `mapstructure:"license_update_base_time" json:"-"`
|
LicenseUpdateBaseTime *string `mapstructure:"license_update_base_time" json:"-"`
|
||||||
LicenseUpdateMaxTime *string `mapstructure:"license_update_max_time" json:"-"`
|
LicenseUpdateMaxTime *string `mapstructure:"license_update_max_time" json:"-"`
|
||||||
|
|
||||||
|
// license reporting
|
||||||
|
Reporting Reporting `mapstructure:"reporting" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GossipLANConfig struct {
|
type GossipLANConfig struct {
|
||||||
|
@ -956,3 +959,11 @@ type RaftBoltDBConfigRaw struct {
|
||||||
type RaftWALConfigRaw struct {
|
type RaftWALConfigRaw struct {
|
||||||
SegmentSizeMB *int `mapstructure:"segment_size_mb" json:"segment_size_mb,omitempty"`
|
SegmentSizeMB *int `mapstructure:"segment_size_mb" json:"segment_size_mb,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type License struct {
|
||||||
|
Enabled *bool `mapstructure:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reporting struct {
|
||||||
|
License License `mapstructure:"license"`
|
||||||
|
}
|
||||||
|
|
|
@ -1484,9 +1484,19 @@ type RuntimeConfig struct {
|
||||||
// here so that tests can use a smaller value.
|
// here so that tests can use a smaller value.
|
||||||
LocalProxyConfigResyncInterval time.Duration
|
LocalProxyConfigResyncInterval time.Duration
|
||||||
|
|
||||||
|
Reporting ReportingConfig
|
||||||
|
|
||||||
EnterpriseRuntimeConfig
|
EnterpriseRuntimeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LicenseConfig struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReportingConfig struct {
|
||||||
|
License LicenseConfig
|
||||||
|
}
|
||||||
|
|
||||||
type AutoConfig struct {
|
type AutoConfig struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
IntroToken string
|
IntroToken string
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/sdk/testutil"
|
"github.com/hashicorp/consul/sdk/testutil"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testRuntimeConfigSanitizeExpectedFilename = "TestRuntimeConfig_Sanitize.golden"
|
var testRuntimeConfigSanitizeExpectedFilename = "TestRuntimeConfig_Sanitize.golden"
|
||||||
|
@ -31,6 +32,7 @@ var enterpriseConfigKeyWarnings = []string{
|
||||||
enterpriseConfigKeyError{key: "acl.msp_disable_bootstrap"}.Error(),
|
enterpriseConfigKeyError{key: "acl.msp_disable_bootstrap"}.Error(),
|
||||||
enterpriseConfigKeyError{key: "acl.tokens.managed_service_provider"}.Error(),
|
enterpriseConfigKeyError{key: "acl.tokens.managed_service_provider"}.Error(),
|
||||||
enterpriseConfigKeyError{key: "audit"}.Error(),
|
enterpriseConfigKeyError{key: "audit"}.Error(),
|
||||||
|
enterpriseConfigKeyError{key: "reporting.license.enabled"}.Error(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSS-only equivalent of TestConfigFlagsAndEdgecases
|
// OSS-only equivalent of TestConfigFlagsAndEdgecases
|
||||||
|
@ -87,3 +89,82 @@ func TestLoad_IntegrationWithFlags_OSS(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoad_ReportingConfig(t *testing.T) {
|
||||||
|
dir := testutil.TempDir(t, t.Name())
|
||||||
|
|
||||||
|
t.Run("load from JSON defaults to false", func(t *testing.T) {
|
||||||
|
content := `{
|
||||||
|
"reporting": {}
|
||||||
|
}`
|
||||||
|
|
||||||
|
opts := LoadOpts{
|
||||||
|
FlagValues: FlagValuesTarget{Config: Config{
|
||||||
|
DataDir: &dir,
|
||||||
|
}},
|
||||||
|
Overrides: []Source{
|
||||||
|
FileSource{
|
||||||
|
Name: "reporting.json",
|
||||||
|
Format: "json",
|
||||||
|
Data: content,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
patchLoadOptsShims(&opts)
|
||||||
|
result, err := Load(opts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, result.Warnings, 0)
|
||||||
|
require.Equal(t, false, result.RuntimeConfig.Reporting.License.Enabled)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("load from HCL defaults to false", func(t *testing.T) {
|
||||||
|
content := `
|
||||||
|
reporting {}
|
||||||
|
`
|
||||||
|
|
||||||
|
opts := LoadOpts{
|
||||||
|
FlagValues: FlagValuesTarget{Config: Config{
|
||||||
|
DataDir: &dir,
|
||||||
|
}},
|
||||||
|
Overrides: []Source{
|
||||||
|
FileSource{
|
||||||
|
Name: "reporting.hcl",
|
||||||
|
Format: "hcl",
|
||||||
|
Data: content,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
patchLoadOptsShims(&opts)
|
||||||
|
result, err := Load(opts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, result.Warnings, 0)
|
||||||
|
require.Equal(t, false, result.RuntimeConfig.Reporting.License.Enabled)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with value set returns warning and defaults to false", func(t *testing.T) {
|
||||||
|
content := `reporting {
|
||||||
|
license {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
opts := LoadOpts{
|
||||||
|
FlagValues: FlagValuesTarget{Config: Config{
|
||||||
|
DataDir: &dir,
|
||||||
|
}},
|
||||||
|
Overrides: []Source{
|
||||||
|
FileSource{
|
||||||
|
Name: "reporting.hcl",
|
||||||
|
Format: "hcl",
|
||||||
|
Data: content,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
patchLoadOptsShims(&opts)
|
||||||
|
result, err := Load(opts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, result.Warnings, 1)
|
||||||
|
require.Contains(t, result.Warnings[0], "\"reporting.license.enabled\" is a Consul Enterprise configuration and will have no effect")
|
||||||
|
require.Equal(t, false, result.RuntimeConfig.Reporting.License.Enabled)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -295,6 +295,11 @@
|
||||||
"ReconnectTimeoutLAN": "0s",
|
"ReconnectTimeoutLAN": "0s",
|
||||||
"ReconnectTimeoutWAN": "0s",
|
"ReconnectTimeoutWAN": "0s",
|
||||||
"RejoinAfterLeave": false,
|
"RejoinAfterLeave": false,
|
||||||
|
"Reporting": {
|
||||||
|
"License": {
|
||||||
|
"Enabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"RequestLimitsMode": 0,
|
"RequestLimitsMode": 0,
|
||||||
"RequestLimitsReadRate": 0,
|
"RequestLimitsReadRate": 0,
|
||||||
"RequestLimitsWriteRate": 0,
|
"RequestLimitsWriteRate": 0,
|
||||||
|
|
|
@ -375,6 +375,11 @@ reconnect_timeout = "23739s"
|
||||||
reconnect_timeout_wan = "26694s"
|
reconnect_timeout_wan = "26694s"
|
||||||
recursors = [ "63.38.39.58", "92.49.18.18" ]
|
recursors = [ "63.38.39.58", "92.49.18.18" ]
|
||||||
rejoin_after_leave = true
|
rejoin_after_leave = true
|
||||||
|
reporting = {
|
||||||
|
license = {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
retry_interval = "8067s"
|
retry_interval = "8067s"
|
||||||
retry_interval_wan = "28866s"
|
retry_interval_wan = "28866s"
|
||||||
retry_join = [ "pbsSFY7U", "l0qLtWij" ]
|
retry_join = [ "pbsSFY7U", "l0qLtWij" ]
|
||||||
|
|
|
@ -428,6 +428,11 @@
|
||||||
"92.49.18.18"
|
"92.49.18.18"
|
||||||
],
|
],
|
||||||
"rejoin_after_leave": true,
|
"rejoin_after_leave": true,
|
||||||
|
"reporting": {
|
||||||
|
"license": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"retry_interval": "8067s",
|
"retry_interval": "8067s",
|
||||||
"retry_interval_wan": "28866s",
|
"retry_interval_wan": "28866s",
|
||||||
"retry_join": [
|
"retry_join": [
|
||||||
|
|
|
@ -441,6 +441,8 @@ type Config struct {
|
||||||
|
|
||||||
Locality *structs.Locality
|
Locality *structs.Locality
|
||||||
|
|
||||||
|
Reporting Reporting
|
||||||
|
|
||||||
// Embedded Consul Enterprise specific configuration
|
// Embedded Consul Enterprise specific configuration
|
||||||
*EnterpriseConfig
|
*EnterpriseConfig
|
||||||
}
|
}
|
||||||
|
@ -676,6 +678,7 @@ type ReloadableConfig struct {
|
||||||
RaftTrailingLogs int
|
RaftTrailingLogs int
|
||||||
HeartbeatTimeout time.Duration
|
HeartbeatTimeout time.Duration
|
||||||
ElectionTimeout time.Duration
|
ElectionTimeout time.Duration
|
||||||
|
Reporting Reporting
|
||||||
}
|
}
|
||||||
|
|
||||||
type RaftLogStoreConfig struct {
|
type RaftLogStoreConfig struct {
|
||||||
|
@ -698,3 +701,11 @@ type RaftBoltDBConfig struct {
|
||||||
type WALConfig struct {
|
type WALConfig struct {
|
||||||
SegmentSize int
|
SegmentSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type License struct {
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reporting struct {
|
||||||
|
License License
|
||||||
|
}
|
||||||
|
|
|
@ -1803,6 +1803,8 @@ func (s *Server) ReloadConfig(config ReloadableConfig) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.updateReportingConfig(config)
|
||||||
|
|
||||||
s.rpcLimiter.Store(rate.NewLimiter(config.RPCRateLimit, config.RPCMaxBurst))
|
s.rpcLimiter.Store(rate.NewLimiter(config.RPCRateLimit, config.RPCMaxBurst))
|
||||||
|
|
||||||
if config.RequestLimits != nil {
|
if config.RequestLimits != nil {
|
||||||
|
|
|
@ -182,3 +182,7 @@ func addSerfMetricsLabels(conf *serf.Config, wan bool, segment string, partition
|
||||||
|
|
||||||
conf.MetricLabels = append(conf.MetricLabels, networkMetric)
|
conf.MetricLabels = append(conf.MetricLabels, networkMetric)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) updateReportingConfig(config ReloadableConfig) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
//go:build !consulent
|
||||||
|
// +build !consulent
|
||||||
|
|
||||||
|
package consul
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/testrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAgent_ReloadConfig_Reporting(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("too slow for testing.Short")
|
||||||
|
}
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
dir1, s := testServerWithConfig(t, func(c *Config) {
|
||||||
|
c.Reporting.License.Enabled = false
|
||||||
|
})
|
||||||
|
defer os.RemoveAll(dir1)
|
||||||
|
defer s.Shutdown()
|
||||||
|
|
||||||
|
testrpc.WaitForTestAgent(t, s.RPC, "dc1")
|
||||||
|
|
||||||
|
require.Equal(t, false, s.config.Reporting.License.Enabled)
|
||||||
|
|
||||||
|
rc := ReloadableConfig{
|
||||||
|
Reporting: Reporting{
|
||||||
|
License: License{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, s.ReloadConfig(rc))
|
||||||
|
|
||||||
|
// Check config reload is no-op
|
||||||
|
require.Equal(t, false, s.config.Reporting.License.Enabled)
|
||||||
|
}
|
Loading…
Reference in New Issue