feat: add reporting config with reload (#16890)

This commit is contained in:
Poonam Jadhav 2023-04-11 15:04:02 -04:00 committed by GitHub
parent 37569837a2
commit 8255cc97f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 248 additions and 0 deletions

View File

@ -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

46
agent/agent_oss_test.go Normal file
View File

@ -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)
}

View File

@ -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
} }

View File

@ -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,

View File

@ -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"`
}

View File

@ -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

View File

@ -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)
})
}

View File

@ -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,

View File

@ -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" ]

View File

@ -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": [

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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)
}