Skip to content

Commit

Permalink
Merge pull request #19006 from ahrtr/v2_deprecation_20241204
Browse files Browse the repository at this point in the history
Deprecate `--v2-deprecation` and schedule to remove it in 3.8
  • Loading branch information
ahrtr authored Dec 6, 2024
2 parents f128d89 + f54c8f5 commit 7bb5596
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 46 deletions.
47 changes: 25 additions & 22 deletions server/config/v2_deprecation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,47 +17,50 @@ package config
type V2DeprecationEnum string

const (
// No longer supported in v3.6
// V2Depr0NotYet means v2store isn't deprecated yet.
// Default in v3.5, and no longer supported in v3.6.
V2Depr0NotYet = V2DeprecationEnum("not-yet")
// No longer supported in v3.6
//
// Deprecated: Please use V2Depr0NotYet.

// Deprecated: to be decommissioned in 3.7. Please use V2Depr0NotYet.
// TODO: remove in 3.7
//revive:disable-next-line:var-naming
V2_DEPR_0_NOT_YET = V2Depr0NotYet
// Default in v3.6. Meaningful v2 state is not allowed.
// The V2 files are maintained for v3.5 rollback.

V2Depr1WriteOnly = V2DeprecationEnum("write-only")
// V2Depr1WriteOnly means only writing v2store is allowed.
// Default in v3.6. Meaningful v2 state is not allowed.
// The V2 files are maintained for v3.5 rollback.
//
// Deprecated: Please use V2Depr1WriteOnly.
V2Depr1WriteOnly = V2DeprecationEnum("write-only")

// Deprecated: to be decommissioned in 3.7. Please use V2Depr1WriteOnly.
// TODO: remove in 3.7
//revive:disable-next-line:var-naming
V2_DEPR_1_WRITE_ONLY = V2Depr1WriteOnly

// V2store is WIPED if found !!!
// V2Depr1WriteOnlyDrop means v2store is WIPED if found !!!
// Will be default in 3.7.
V2Depr1WriteOnlyDrop = V2DeprecationEnum("write-only-drop-data")
// V2store is WIPED if found !!!
//
// Deprecated: Pleae use V2Depr1WriteOnlyDrop.

// Deprecated: to be decommissioned in 3.7. Pleae use V2Depr1WriteOnlyDrop.
// TODO: remove in 3.7
//revive:disable-next-line:var-naming
V2_DEPR_1_WRITE_ONLY_DROP = V2Depr1WriteOnlyDrop

// V2store is neither written nor read. Usage of this configuration is blocking
// V2Depr2Gone means v2store is completely gone. The v2store is
// neither written nor read. Anything related to v2store will be
// cleaned up in v3.8. Usage of this configuration is blocking
// ability to rollback to etcd v3.5.
V2Depr2Gone = V2DeprecationEnum("gone")
// V2store is neither written nor read. Usage of this configuration is blocking
// ability to rollback to etcd v3.5.
//
// Deprecated: Please use V2Depr2Gone

// Deprecated: to be decommissioned in 3.7. Please use V2Depr2Gone.
// TODO: remove in 3.7
//revive:disable-next-line:var-naming
V2_DEPR_2_GONE = V2Depr2Gone

// Default deprecation level.
// V2DeprDefault is the default deprecation level.
V2DeprDefault = V2Depr1WriteOnly
// Default deprecation level.
//
// Deprecated: Please use V2DeprDefault.

// Deprecated: to be decommissioned in 3.7. Please use V2DeprDefault.
// TODO: remove in 3.7
//revive:disable-next-line:var-naming
V2_DEPR_DEFAULT = V2DeprDefault
)
Expand Down
4 changes: 3 additions & 1 deletion server/embed/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,9 @@ type Config struct {
// ExperimentalStopGRPCServiceOnDefrag enables etcd gRPC service to stop serving client requests on defragmentation.
ExperimentalStopGRPCServiceOnDefrag bool `json:"experimental-stop-grpc-service-on-defrag"`

// V2Deprecation describes phase of API & Storage V2 support
// V2Deprecation describes phase of API & Storage V2 support.
// Deprecated and scheduled for removal in v3.8.
// Do not set this field for embedded use cases, as it has no effect. However, setting it will not cause any harm.
V2Deprecation config.V2DeprecationEnum `json:"v2-deprecation"`

// ServerFeatureGate is a server level feature gate
Expand Down
2 changes: 2 additions & 0 deletions server/embed/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized

zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()),
zap.Int("max-learners", sc.ExperimentalMaxLearners),

zap.String("v2-deprecation", string(ec.V2Deprecation)),
)
}

Expand Down
16 changes: 9 additions & 7 deletions server/etcdmain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ var (
deprecatedFlags = map[string]string{
// TODO: remove in 3.7.
"snapshot-count": "--snapshot-count 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.",
}
)

Expand All @@ -74,9 +75,11 @@ type config struct {

// configFlags has the set of flags used for command line parsing a Config
type configFlags struct {
flagSet *flag.FlagSet
clusterState *flags.SelectiveStringValue
fallback *flags.SelectiveStringValue
flagSet *flag.FlagSet
clusterState *flags.SelectiveStringValue
fallback *flags.SelectiveStringValue
// Deprecated and scheduled for removal in v3.8. The default value is enforced, ignoring user input.
// TODO: remove in v3.8.
v2deprecation *flags.SelectiveStringsValue
}

Expand Down Expand Up @@ -108,7 +111,7 @@ func newConfig() *config {
fs.StringVar(&cfg.configFile, "config-file", "", "Path to the server configuration file. Note that if a configuration file is provided, other command line flags and environment variables will be ignored.")
fs.Var(cfg.cf.fallback, "discovery-fallback", fmt.Sprintf("Valid values include %q", cfg.cf.fallback.Valids()))
fs.Var(cfg.cf.clusterState, "initial-cluster-state", "Initial cluster state ('new' when bootstrapping a new cluster or 'existing' when adding new members to an existing cluster). After successful initialization (bootstrapping or adding), flag is ignored on restarts.")
fs.Var(cfg.cf.v2deprecation, "v2-deprecation", fmt.Sprintf("v2store deprecation stage: %q. ", cfg.cf.v2deprecation.Valids()))
fs.Var(cfg.cf.v2deprecation, "v2-deprecation", fmt.Sprintf("v2store deprecation stage: %q. Deprecated and scheduled for removal in v3.8. The default value is enforced, ignoring user input.", cfg.cf.v2deprecation.Valids()))

fs.BoolVar(&cfg.printVersion, "version", false, "Print the version and exit.")
// ignored
Expand Down Expand Up @@ -161,9 +164,8 @@ func (cfg *config) parse(arguments []string) error {
err = cfg.configFromCmdLine()
}

if cfg.ec.V2Deprecation == "" {
cfg.ec.V2Deprecation = cconfig.V2DeprDefault
}
// `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

cfg.ec.WarningUnaryRequestDuration, perr = cfg.parseWarningUnaryRequestDuration()
if perr != nil {
Expand Down
8 changes: 4 additions & 4 deletions server/etcdmain/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ Clustering:
--auto-compaction-mode 'periodic'
Interpret 'auto-compaction-retention' one of: periodic|revision. 'periodic' for duration based retention, defaulting to hours if no time unit is provided (e.g. '5m'). 'revision' for revision number based retention.
--v2-deprecation '` + string(cconfig.V2DeprDefault) + `'
Phase of v2store deprecation. Allows to opt-in for higher compatibility mode.
Phase of v2store deprecation. Deprecated and scheduled for removal in v3.8. The default value is enforced, ignoring user input.
Supported values:
'not-yet' // Issues a warning if v2store have meaningful content (default in v3.5)
'write-only' // Custom v2 state is not allowed (planned default in v3.6)
'write-only-drop-data' // Custom v2 state will get DELETED !
'gone' // v2store is not maintained any longer. (planned default in v3.7)
'write-only' // Custom v2 state is not allowed (default in v3.6)
'write-only-drop-data' // Custom v2 state will get DELETED ! (planned default in v3.7)
'gone' // v2store is not maintained any longer. (planned to cleanup anything related to v2store in v3.8)
Security:
--cert-file ''
Expand Down
74 changes: 62 additions & 12 deletions tests/e2e/etcd_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,17 +666,67 @@ func TestEtcdTLSVersion(t *testing.T) {
func TestEtcdDeprecatedFlags(t *testing.T) {
e2e.SkipInShortMode(t)

proc, err := e2e.SpawnCmd(
[]string{
e2e.BinPath.Etcd,
"--name", "e1",
"--snapshot-count=100",
}, nil,
)
require.NoError(t, err)
require.NoError(t, e2e.WaitReadyExpectProc(context.TODO(), proc, []string{"--snapshot-count is deprecated in 3.6 and will be decommissioned in 3.7"}))
require.NoError(t, proc.Stop())
commonArgs := []string{
e2e.BinPath.Etcd,
"--name", "e1",
}

proc.Wait() // ensure the port has been released
proc.Close()
testCases := []struct {
name string
args []string
expectedMsg string
}{
{
name: "snapshot-count",
args: append(commonArgs, "--snapshot-count=100"),
expectedMsg: "--snapshot-count is deprecated in 3.6 and will be decommissioned in 3.7",
},
{
name: "v2-deprecation",
args: append(commonArgs, "--v2-deprecation", "write-only-drop-data"),
expectedMsg: "--v2-deprecation is deprecated and scheduled for removal in v3.8. The default value is enforced, ignoring user input",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
proc, err := e2e.SpawnCmd(
tc.args, nil,
)
require.NoError(t, err)
require.NoError(t, e2e.WaitReadyExpectProc(context.TODO(), proc, []string{tc.expectedMsg}))
require.NoError(t, proc.Stop())

proc.Wait() // ensure the port has been released
proc.Close()
})
}
}

// TestV2DeprecationEnforceDefaultValue verifies that etcd enforces the default V2Deprecation level
// and ignores users input.
func TestV2DeprecationEnforceDefaultValue(t *testing.T) {
e2e.SkipInShortMode(t)

commonArgs := []string{
e2e.BinPath.Etcd,
"--name", "e1",
}

validV2DeprecationLevels := []string{"write-only", "write-only-drop-data", "gone"}
expectedDeprecationLevelMsg := `"v2-deprecation":"write-only"`

for _, optionLevel := range validV2DeprecationLevels {
t.Run(optionLevel, func(t *testing.T) {
proc, err := e2e.SpawnCmd(
append(commonArgs, "--v2-deprecation", optionLevel), nil,
)
require.NoError(t, err)
require.NoError(t, e2e.WaitReadyExpectProc(context.TODO(), proc, []string{expectedDeprecationLevelMsg}))
require.NoError(t, proc.Stop())

proc.Wait() // ensure the port has been released
proc.Close()
})
}
}

0 comments on commit 7bb5596

Please sign in to comment.