migrate experimental-compact-hash-check-enabled to feature gate.

Signed-off-by: Siyuan Zhang <sizhang@google.com>
This commit is contained in:
Siyuan Zhang 2024-12-12 16:35:02 -08:00
parent b4450d510d
commit 85363bda32
12 changed files with 262 additions and 42 deletions

View File

@ -91,6 +91,8 @@ type FeatureGate interface {
// set on the copy without mutating the original. This is useful for validating
// config against potential feature gate changes before committing those changes.
DeepCopy() MutableFeatureGate
// String returns a string containing all enabled feature gates, formatted as "key1=value1,key2=value2,...".
String() string
}
// MutableFeatureGate parses and stores flag gates for known features from

View File

@ -147,10 +147,9 @@ type ServerConfig struct {
// InitialCorruptCheck is true to check data corruption on boot
// before serving any peer/client traffic.
InitialCorruptCheck bool
CorruptCheckTime time.Duration
CompactHashCheckEnabled bool
CompactHashCheckTime time.Duration
InitialCorruptCheck bool
CorruptCheckTime time.Duration
CompactHashCheckTime time.Duration
// PreVote is true to enable Raft Pre-Vote.
PreVote bool

View File

@ -58,21 +58,21 @@ const (
ClusterStateFlagNew = "new"
ClusterStateFlagExisting = "existing"
DefaultName = "default"
DefaultMaxSnapshots = 5
DefaultMaxWALs = 5
DefaultMaxTxnOps = uint(128)
DefaultWarningApplyDuration = 100 * time.Millisecond
DefaultWarningUnaryRequestDuration = 300 * time.Millisecond
DefaultMaxRequestBytes = 1.5 * 1024 * 1024
DefaultMaxConcurrentStreams = math.MaxUint32
DefaultGRPCKeepAliveMinTime = 5 * time.Second
DefaultGRPCKeepAliveInterval = 2 * time.Hour
DefaultGRPCKeepAliveTimeout = 20 * time.Second
DefaultDowngradeCheckTime = 5 * time.Second
DefaultAutoCompactionMode = "periodic"
DefaultAuthToken = "simple"
DefaultExperimentalCompactHashCheckTime = time.Minute
DefaultName = "default"
DefaultMaxSnapshots = 5
DefaultMaxWALs = 5
DefaultMaxTxnOps = uint(128)
DefaultWarningApplyDuration = 100 * time.Millisecond
DefaultWarningUnaryRequestDuration = 300 * time.Millisecond
DefaultMaxRequestBytes = 1.5 * 1024 * 1024
DefaultMaxConcurrentStreams = math.MaxUint32
DefaultGRPCKeepAliveMinTime = 5 * time.Second
DefaultGRPCKeepAliveInterval = 2 * time.Hour
DefaultGRPCKeepAliveTimeout = 20 * time.Second
DefaultDowngradeCheckTime = 5 * time.Second
DefaultAutoCompactionMode = "periodic"
DefaultAuthToken = "simple"
DefaultCompactHashCheckTime = time.Minute
DefaultDiscoveryDialTimeout = 2 * time.Second
DefaultDiscoveryRequestTimeOut = 5 * time.Second
@ -128,6 +128,13 @@ var (
// indirection for testing
getCluster = srv.GetCluster
// in 3.6, we are migration all the --experimental flags to feature gate and flags without the prefix.
// This is the mapping from the non boolean `experimental-` to the new flags.
// TODO: delete in v3.7
experimentalNonBoolFlagMigrationMap = map[string]string{
"experimental-compact-hash-check-time": "compact-hash-check-time",
}
)
var (
@ -356,10 +363,17 @@ type Config struct {
// AuthTokenTTL in seconds of the simple token
AuthTokenTTL uint `json:"auth-token-ttl"`
ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"`
ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"`
ExperimentalCompactHashCheckEnabled bool `json:"experimental-compact-hash-check-enabled"`
ExperimentalCompactHashCheckTime time.Duration `json:"experimental-compact-hash-check-time"`
ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"`
ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"`
// ExperimentalCompactHashCheckEnabled enables leader to periodically check followers compaction hashes.
// Deprecated in v3.6 and will be decommissioned in v3.7.
// TODO: delete in v3.7
ExperimentalCompactHashCheckEnabled bool `json:"experimental-compact-hash-check-enabled"`
// ExperimentalCompactHashCheckTime is the duration of time between leader checks followers compaction hashes.
// Deprecated in v3.6 and will be decommissioned in v3.7.
// TODO: delete in v3.7
ExperimentalCompactHashCheckTime time.Duration `json:"experimental-compact-hash-check-time"`
CompactHashCheckTime time.Duration `json:"compact-hash-check-time"`
// ExperimentalEnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change.
ExperimentalEnableLeaseCheckpoint bool `json:"experimental-enable-lease-checkpoint"`
@ -468,6 +482,8 @@ type Config struct {
// ServerFeatureGate is a server level feature gate
ServerFeatureGate featuregate.FeatureGate
// FlagsExplicitlySet stores if a flag is explicitly set from the cmd line or config file.
FlagsExplicitlySet map[string]bool
}
// configYAML holds the config suitable for yaml parsing
@ -573,8 +589,9 @@ func NewConfig() *Config {
ExperimentalStopGRPCServiceOnDefrag: false,
ExperimentalMaxLearners: membership.DefaultMaxLearners,
ExperimentalCompactHashCheckEnabled: false,
ExperimentalCompactHashCheckTime: DefaultExperimentalCompactHashCheckTime,
CompactHashCheckTime: DefaultCompactHashCheckTime,
// TODO: delete in v3.7
ExperimentalCompactHashCheckTime: DefaultCompactHashCheckTime,
V2Deprecation: config.V2DeprDefault,
@ -592,6 +609,7 @@ func NewConfig() *Config {
AutoCompactionMode: DefaultAutoCompactionMode,
ServerFeatureGate: features.NewDefaultServerFeatureGate(DefaultName, nil),
FlagsExplicitlySet: map[string]bool{},
}
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
return cfg
@ -755,8 +773,11 @@ func (cfg *Config) AddFlags(fs *flag.FlagSet) {
// experimental
fs.BoolVar(&cfg.ExperimentalInitialCorruptCheck, "experimental-initial-corrupt-check", cfg.ExperimentalInitialCorruptCheck, "Enable to check data corruption before serving any client/peer traffic.")
fs.DurationVar(&cfg.ExperimentalCorruptCheckTime, "experimental-corrupt-check-time", cfg.ExperimentalCorruptCheckTime, "Duration of time between cluster corruption check passes.")
fs.BoolVar(&cfg.ExperimentalCompactHashCheckEnabled, "experimental-compact-hash-check-enabled", cfg.ExperimentalCompactHashCheckEnabled, "Enable leader to periodically check followers compaction hashes.")
fs.DurationVar(&cfg.ExperimentalCompactHashCheckTime, "experimental-compact-hash-check-time", cfg.ExperimentalCompactHashCheckTime, "Duration of time between leader checks followers compaction hashes.")
// TODO: delete in v3.7
fs.BoolVar(&cfg.ExperimentalCompactHashCheckEnabled, "experimental-compact-hash-check-enabled", cfg.ExperimentalCompactHashCheckEnabled, "Enable leader to periodically check followers compaction hashes. Deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=CompactHashCheck=true' instead")
fs.DurationVar(&cfg.ExperimentalCompactHashCheckTime, "experimental-compact-hash-check-time", cfg.ExperimentalCompactHashCheckTime, "Duration of time between leader checks followers compaction hashes. Deprecated in v3.6 and will be decommissioned in v3.7. Use --compact-hash-check-time instead.")
fs.DurationVar(&cfg.CompactHashCheckTime, "compact-hash-check-time", cfg.CompactHashCheckTime, "Duration of time between leader checks followers compaction hashes.")
fs.BoolVar(&cfg.ExperimentalEnableLeaseCheckpoint, "experimental-enable-lease-checkpoint", false, "Enable leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change.")
// TODO: delete in v3.7
@ -817,6 +838,11 @@ func (cfg *configYAML) configFromFile(path string) error {
if err != nil {
return err
}
for flg := range cfgMap {
cfg.FlagsExplicitlySet[flg] = true
}
getBoolFlagVal := func(flagName string) *bool {
flagVal, ok := cfgMap[flagName]
if !ok {
@ -979,6 +1005,14 @@ func updateMinMaxVersions(info *transport.TLSInfo, min, max string) {
// Validate ensures that '*embed.Config' fields are properly configured.
func (cfg *Config) Validate() error {
// make sure there is no conflict in the flag settings in the ExperimentalNonBoolFlagMigrationMap
// TODO: delete in v3.7
for oldFlag, newFlag := range experimentalNonBoolFlagMigrationMap {
if cfg.FlagsExplicitlySet[oldFlag] && cfg.FlagsExplicitlySet[newFlag] {
return fmt.Errorf("cannot set --%s and --%s at the same time, please use --%s only", oldFlag, newFlag, newFlag)
}
}
if err := cfg.setupLogging(); err != nil {
return err
}
@ -1083,10 +1117,13 @@ func (cfg *Config) Validate() error {
if cfg.ExperimentalEnableLeaseCheckpointPersist && !cfg.ExperimentalEnableLeaseCheckpoint {
return fmt.Errorf("setting experimental-enable-lease-checkpoint-persist requires experimental-enable-lease-checkpoint")
}
// TODO: delete in v3.7
if cfg.ExperimentalCompactHashCheckTime <= 0 {
return fmt.Errorf("--experimental-compact-hash-check-time must be >0 (set to %v)", cfg.ExperimentalCompactHashCheckTime)
}
if cfg.CompactHashCheckTime <= 0 {
return fmt.Errorf("--compact-hash-check-time must be >0 (set to %v)", cfg.CompactHashCheckTime)
}
// If `--name` isn't configured, then multiple members may have the same "default" name.
// When adding a new member with the "default" name as well, etcd may regards its peerURL

View File

@ -98,6 +98,7 @@ func TestConfigFileFeatureGates(t *testing.T) {
serverFeatureGatesJSON string
experimentalStopGRPCServiceOnDefrag string
experimentalInitialCorruptCheck string
experimentalCompactHashCheckEnabled string
expectErr bool
expectedFeatures map[featuregate.Feature]bool
}{
@ -194,12 +195,46 @@ func TestConfigFileFeatureGates(t *testing.T) {
features.InitialCorruptCheck: false,
},
},
{
name: "cannot set both experimental flag and feature gate flag for ExperimentalCompactHashCheckEnabled",
serverFeatureGatesJSON: "CompactHashCheck=true",
experimentalCompactHashCheckEnabled: "false",
expectErr: true,
},
{
name: "can set feature gate experimentalCompactHashCheckEnabled to true from experimental flag",
experimentalCompactHashCheckEnabled: "true",
expectedFeatures: map[featuregate.Feature]bool{
features.StopGRPCServiceOnDefrag: false,
features.DistributedTracing: false,
features.CompactHashCheck: true,
},
},
{
name: "can set feature gate experimentalCompactHashCheckEnabled to false from experimental flag",
experimentalCompactHashCheckEnabled: "false",
expectedFeatures: map[featuregate.Feature]bool{
features.StopGRPCServiceOnDefrag: false,
features.DistributedTracing: false,
features.CompactHashCheck: false,
},
},
{
name: "can set feature gate CompactHashCheck to true from feature gate flag",
serverFeatureGatesJSON: "CompactHashCheck=true",
expectedFeatures: map[featuregate.Feature]bool{
features.StopGRPCServiceOnDefrag: false,
features.DistributedTracing: false,
features.CompactHashCheck: true,
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
yc := struct {
ExperimentalStopGRPCServiceOnDefrag *bool `json:"experimental-stop-grpc-service-on-defrag,omitempty"`
ExperimentalInitialCorruptCheck *bool `json:"experimental-initial-corrupt-check,omitempty"`
ExperimentalCompactHashCheckEnabled *bool `json:"experimental-compact-hash-check-enabled,omitempty"`
ServerFeatureGatesJSON string `json:"feature-gates"`
}{
ServerFeatureGatesJSON: tc.serverFeatureGatesJSON,
@ -221,6 +256,14 @@ func TestConfigFileFeatureGates(t *testing.T) {
yc.ExperimentalStopGRPCServiceOnDefrag = &experimentalStopGRPCServiceOnDefrag
}
if tc.experimentalCompactHashCheckEnabled != "" {
experimentalCompactHashCheckEnabled, err := strconv.ParseBool(tc.experimentalCompactHashCheckEnabled)
if err != nil {
t.Fatal(err)
}
yc.ExperimentalCompactHashCheckEnabled = &experimentalCompactHashCheckEnabled
}
b, err := yaml.Marshal(&yc)
if err != nil {
t.Fatal(err)

View File

@ -205,8 +205,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) {
CORS: cfg.CORS,
HostWhitelist: cfg.HostWhitelist,
CorruptCheckTime: cfg.ExperimentalCorruptCheckTime,
CompactHashCheckEnabled: cfg.ExperimentalCompactHashCheckEnabled,
CompactHashCheckTime: cfg.ExperimentalCompactHashCheckTime,
CompactHashCheckTime: cfg.CompactHashCheckTime,
PreVote: cfg.PreVote,
Logger: cfg.logger,
ForceNewCluster: cfg.ForceNewCluster,
@ -351,9 +350,9 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized
zap.Uint32("max-concurrent-streams", sc.MaxConcurrentStreams),
zap.Bool("pre-vote", sc.PreVote),
zap.String(ServerFeatureGateFlagName, sc.ServerFeatureGate.String()),
zap.Bool("initial-corrupt-check", sc.InitialCorruptCheck),
zap.String("corrupt-check-time-interval", sc.CorruptCheckTime.String()),
zap.Bool("compact-check-time-enabled", sc.CompactHashCheckEnabled),
zap.Duration("compact-check-time-interval", sc.CompactHashCheckTime),
zap.String("auto-compaction-mode", sc.AutoCompactionMode),
zap.Duration("auto-compaction-retention", sc.AutoCompactionRetention),

View File

@ -62,6 +62,8 @@ var (
"snapshot-count": "--snapshot-count is deprecated in 3.6 and will be decommissioned in 3.7.",
"max-snapshots": "--max-snapshots is deprecated in 3.6 and will be decommissioned in 3.7.",
"v2-deprecation": "--v2-deprecation is deprecated and scheduled for removal in v3.8. The default value is enforced, ignoring user input.",
"experimental-compact-hash-check-enabled": "--experimental-compact-hash-check-enabled is deprecated in 3.6 and will be decommissioned in 3.7. Use '--feature-gates=CompactHashCheck=true' instead.",
"experimental-compact-hash-check-time": "--experimental-compact-hash-check-time is deprecated in 3.6 and will be decommissioned in 3.7. Use '--compact-hash-check-time' instead.",
}
)
@ -165,6 +167,12 @@ func (cfg *config) parse(arguments []string) error {
err = cfg.configFromCmdLine()
}
// params related to experimental flag deprecation
// TODO: delete in v3.7
if cfg.ec.FlagsExplicitlySet["experimental-compact-hash-check-time"] {
cfg.ec.CompactHashCheckTime = cfg.ec.ExperimentalCompactHashCheckTime
}
// `V2Deprecation` (--v2-deprecation) is deprecated and scheduled for removal in v3.8. The default value is enforced, ignoring user input.
cfg.ec.V2Deprecation = cconfig.V2DeprDefault
@ -260,6 +268,10 @@ func (cfg *config) configFromCmdLine() error {
cfg.ec.InitialCluster = ""
}
cfg.cf.flagSet.Visit(func(f *flag.Flag) {
cfg.ec.FlagsExplicitlySet[f.Name] = true
})
getBoolFlagVal := func(flagName string) *bool {
boolVal, parseErr := flags.GetBoolFlagVal(cfg.cf.flagSet, flagName)
if parseErr != nil {

View File

@ -23,6 +23,7 @@ import (
"reflect"
"strings"
"testing"
"time"
"sigs.k8s.io/yaml"
@ -475,6 +476,99 @@ func TestParseFeatureGateFlags(t *testing.T) {
}
}
// TestCompactHashCheckTimeFlagMigration tests the migration from
// --experimental-compact-hash-check-time to --compact-hash-check-time
// TODO: delete in v3.7
func TestCompactHashCheckTimeFlagMigration(t *testing.T) {
testCases := []struct {
name string
compactHashCheckTime string
experimentalCompactHashCheckTime string
useConfigFile bool
expectErr bool
expectedCompactHashCheckTime time.Duration
}{
{
name: "default",
expectedCompactHashCheckTime: time.Minute,
},
{
name: "cannot set both experimental flag and non experimental flag",
compactHashCheckTime: "2m",
experimentalCompactHashCheckTime: "3m",
expectErr: true,
},
{
name: "can set experimental flag",
experimentalCompactHashCheckTime: "3m",
expectedCompactHashCheckTime: 3 * time.Minute,
},
{
name: "can set non experimental flag",
compactHashCheckTime: "2m",
expectedCompactHashCheckTime: 2 * time.Minute,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cmdLineArgs := []string{}
yc := struct {
ExperimentalCompactHashCheckTime time.Duration `json:"experimental-compact-hash-check-time,omitempty"`
CompactHashCheckTime time.Duration `json:"compact-hash-check-time,omitempty"`
}{}
if tc.compactHashCheckTime != "" {
cmdLineArgs = append(cmdLineArgs, fmt.Sprintf("--compact-hash-check-time=%s", tc.compactHashCheckTime))
compactHashCheckTime, err := time.ParseDuration(tc.compactHashCheckTime)
if err != nil {
t.Fatal(err)
}
yc.CompactHashCheckTime = compactHashCheckTime
}
if tc.experimentalCompactHashCheckTime != "" {
cmdLineArgs = append(cmdLineArgs, fmt.Sprintf("--experimental-compact-hash-check-time=%s", tc.experimentalCompactHashCheckTime))
experimentalCompactHashCheckTime, err := time.ParseDuration(tc.experimentalCompactHashCheckTime)
if err != nil {
t.Fatal(err)
}
yc.ExperimentalCompactHashCheckTime = experimentalCompactHashCheckTime
}
b, err := yaml.Marshal(&yc)
if err != nil {
t.Fatal(err)
}
tmpfile := mustCreateCfgFile(t, b)
defer os.Remove(tmpfile.Name())
cfgFromCmdLine := newConfig()
errFromCmdLine := cfgFromCmdLine.parse(cmdLineArgs)
cfgFromFile := newConfig()
errFromFile := cfgFromFile.parse([]string{fmt.Sprintf("--config-file=%s", tmpfile.Name())})
if tc.expectErr {
if errFromCmdLine == nil || errFromFile == nil {
t.Fatal("expect parse error")
}
return
}
if errFromCmdLine != nil || errFromFile != nil {
t.Fatal(err)
}
if cfgFromCmdLine.ec.CompactHashCheckTime != tc.expectedCompactHashCheckTime {
t.Errorf("expected CompactHashCheckTime=%v, got %v", tc.expectedCompactHashCheckTime, cfgFromCmdLine.ec.CompactHashCheckTime)
}
if cfgFromFile.ec.CompactHashCheckTime != tc.expectedCompactHashCheckTime {
t.Errorf("expected CompactHashCheckTime=%v, got %v", tc.expectedCompactHashCheckTime, cfgFromFile.ec.CompactHashCheckTime)
}
})
}
}
func mustCreateCfgFile(t *testing.T, b []byte) *os.File {
tmpfile, err := os.CreateTemp("", "servercfg")
if err != nil {

View File

@ -277,9 +277,11 @@ Experimental feature:
Enable to check data corruption before serving any client/peer traffic.
--experimental-corrupt-check-time '0s'
Duration of time between cluster corruption check passes.
--experimental-compact-hash-check-enabled 'false'
--experimental-compact-hash-check-enabled 'false'. Deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=CompactHashCheck=true' instead.
Enable leader to periodically check followers compaction hashes.
--experimental-compact-hash-check-time '1m'
Duration of time between leader checks followers compaction hashes. Deprecated in v3.6 and will be decommissioned in v3.7. Use '--compact-hash-check-time' instead.
--compact-hash-check-time '1m'
Duration of time between leader checks followers compaction hashes.
--experimental-enable-lease-checkpoint 'false'
ExperimentalEnableLeaseCheckpoint enables primary lessor to persist lease remainingTTL to prevent indefinite auto-renewal of long lived leases.

View File

@ -64,6 +64,7 @@ import (
"go.etcd.io/etcd/server/v3/etcdserver/errors"
"go.etcd.io/etcd/server/v3/etcdserver/txn"
serverversion "go.etcd.io/etcd/server/v3/etcdserver/version"
"go.etcd.io/etcd/server/v3/features"
"go.etcd.io/etcd/server/v3/lease"
"go.etcd.io/etcd/server/v3/lease/leasehttp"
serverstorage "go.etcd.io/etcd/server/v3/storage"
@ -2328,7 +2329,7 @@ func (s *EtcdServer) monitorKVHash() {
}
func (s *EtcdServer) monitorCompactHash() {
if !s.Cfg.CompactHashCheckEnabled {
if !s.FeatureEnabled(features.CompactHashCheck) {
return
}
t := s.Cfg.CompactHashCheckTime

View File

@ -50,6 +50,11 @@ const (
// alpha: v3.6
// main PR: https://github.com/etcd-io/etcd/pull/10524
InitialCorruptCheck featuregate.Feature = "InitialCorruptCheck"
// CompactHashCheck enables leader to periodically check followers compaction hashes.
// owner: @serathius
// alpha: v3.6
// main PR: https://github.com/etcd-io/etcd/pull/14120
CompactHashCheck featuregate.Feature = "CompactHashCheck"
)
var (
@ -57,6 +62,7 @@ var (
DistributedTracing: {Default: false, PreRelease: featuregate.Alpha},
StopGRPCServiceOnDefrag: {Default: false, PreRelease: featuregate.Alpha},
InitialCorruptCheck: {Default: false, PreRelease: featuregate.Alpha},
CompactHashCheck: {Default: false, PreRelease: featuregate.Alpha},
}
// ExperimentalFlagToFeatureMap is the map from the cmd line flags of experimental features
// to their corresponding feature gates.
@ -64,6 +70,7 @@ var (
ExperimentalFlagToFeatureMap = map[string]featuregate.Feature{
"experimental-stop-grpc-service-on-defrag": StopGRPCServiceOnDefrag,
"experimental-initial-corrupt-check": InitialCorruptCheck,
"experimental-compact-hash-check-enabled": CompactHashCheck,
}
)

View File

@ -228,15 +228,25 @@ func TestPeriodicCheckDetectsCorruption(t *testing.T) {
}
func TestCompactHashCheckDetectCorruption(t *testing.T) {
testCompactHashCheckDetectCorruption(t, false)
}
func TestCompactHashCheckDetectCorruptionWithFeatureGate(t *testing.T) {
testCompactHashCheckDetectCorruption(t, true)
}
func testCompactHashCheckDetectCorruption(t *testing.T, useFeatureGate bool) {
checkTime := time.Second
e2e.BeforeTest(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
epc, err := e2e.NewEtcdProcessCluster(ctx, t,
e2e.WithKeepDataDir(true),
e2e.WithCompactHashCheckEnabled(true),
e2e.WithCompactHashCheckTime(checkTime),
)
opts := []e2e.EPClusterOption{e2e.WithKeepDataDir(true), e2e.WithCompactHashCheckTime(checkTime)}
if useFeatureGate {
opts = append(opts, e2e.WithServerFeatureGate("CompactHashCheck", true))
} else {
opts = append(opts, e2e.WithCompactHashCheckEnabled(true))
}
epc, err := e2e.NewEtcdProcessCluster(ctx, t, opts...)
if err != nil {
t.Fatalf("could not start etcd process cluster (%v)", err)
}
@ -270,6 +280,14 @@ func TestCompactHashCheckDetectCorruption(t *testing.T) {
}
func TestCompactHashCheckDetectCorruptionInterrupt(t *testing.T) {
testCompactHashCheckDetectCorruptionInterrupt(t, false)
}
func TestCompactHashCheckDetectCorruptionInterruptWithFeatureGate(t *testing.T) {
testCompactHashCheckDetectCorruptionInterrupt(t, true)
}
func testCompactHashCheckDetectCorruptionInterrupt(t *testing.T, useFeatureGate bool) {
checkTime := time.Second
e2e.BeforeTest(t)
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
@ -281,14 +299,20 @@ func TestCompactHashCheckDetectCorruptionInterrupt(t *testing.T) {
t.Log("creating a new cluster with 3 nodes...")
dataDirPath := t.TempDir()
cfg := e2e.NewConfig(
opts := []e2e.EPClusterOption{
e2e.WithKeepDataDir(true),
e2e.WithCompactHashCheckEnabled(true),
e2e.WithCompactHashCheckTime(checkTime),
e2e.WithClusterSize(3),
e2e.WithDataDirPath(dataDirPath),
e2e.WithLogLevel("info"),
)
}
if useFeatureGate {
opts = append(opts, e2e.WithServerFeatureGate("CompactHashCheck", true))
} else {
opts = append(opts, e2e.WithCompactHashCheckEnabled(true))
}
cfg := e2e.NewConfig(opts...)
epc, err := e2e.InitEtcdProcessCluster(t, cfg)
require.NoError(t, err)

View File

@ -328,7 +328,7 @@ func WithCompactHashCheckEnabled(enabled bool) EPClusterOption {
}
func WithCompactHashCheckTime(time time.Duration) EPClusterOption {
return func(c *EtcdProcessClusterConfig) { c.ServerConfig.ExperimentalCompactHashCheckTime = time }
return func(c *EtcdProcessClusterConfig) { c.ServerConfig.CompactHashCheckTime = time }
}
func WithGoFailEnabled(enabled bool) EPClusterOption {