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

Etcd Downgrade backend #11492

Closed
wants to merge 8 commits into from
Closed

Conversation

YoyinZyc
Copy link
Contributor

@YoyinZyc YoyinZyc commented Jan 4, 2020

The original downgrade PR is too big to review. I will break it down into multiple small PRs.
This pr contains the server side of downgrade. The unit tests will be added in following PRs.

Based on the discussion here, the cluster only allows member with downgrade target version to join in during downgrading.
For more information about the design, please go to #11362
@gyuho @jingyih @wenjiaswe @hexfusion PTAL Thanks:)

@jingyih jingyih requested review from gyuho and jingyih January 15, 2020 08:48
@@ -778,6 +796,36 @@ func clusterVersionFromBackend(lg *zap.Logger, be backend.Backend) *semver.Versi
return semver.Must(semver.NewVersion(string(vals[0])))
}

func downgradeInfoFromBackend(lg *zap.Logger, be backend.Backend) *DowngradeInfo {
dkey := backendDowngradeKey()
if be != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we panic on be == nil? So, we can reduce indentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Move nil check outside downgradeInfoFromBackend to reduce indentation.

}

if len(keys) != 1 {
if lg != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, do we really need nil checks on logger?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't quite get it. Since we haven't deprecated plog and used zap log as default, lg is set to nil as default if flag --logger=zap is not enabled. I think we can remove all the nil check of log after we enable zap log as default?

Copy link
Contributor

Choose a reason for hiding this comment

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

I meant, if we set logger to https://godoc.org/go.uber.org/zap#NewNop once in the caller, all the downstream calls need not handle this nil checks?

if d != nil && d.Enabled && d.TargetVersion != nil {
if isValidDowngrade(d.TargetVersion, lv) {
if cv != nil {
if lg != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same. Can previous calls ensure logger is always non-nil?

}
}
}

// isValidDowngrade checks whether joining local server is a valid downgrade when cluster enables downgrade.
// the validation passes when local version is one minor version higher then target version
func isValidDowngrade(tv *semver.Version, lv *semver.Version) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

this needs unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it has unit test but not in this pr. I thought it will be a big pr if I include all the tests. Should I put them in or just add the unit tests?

dkey := backendDowngradeKey()
dvalue, err := json.Marshal(downgrade)
if err != nil {
if lg != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, can previous calls ensure logger is non-nil always?

}
tx := be.BatchTx()
tx.Lock()
defer tx.Unlock()
Copy link
Contributor

@gyuho gyuho Jan 21, 2020

Choose a reason for hiding this comment

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

unnecessary defer we can just place it under UnsafePut?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -177,6 +177,21 @@ func getVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt
return vers
}

// allowedVersionRange decides the available version range of the cluster that local server can join in;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can these be unit tested?


targetVersion := d.TargetVersion
if isDowngradeFinished(s.getLogger(), targetVersion, getVersions(s.getLogger(), s.cluster, s.id, s.peerRt)) {
if lg != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here as well, logger nil checking should be handled at the top level. Downstream packages should not worry about this checks.

@jingyih
Copy link
Contributor

jingyih commented Jan 30, 2020

@gyuho, regarding the logger, today in master, we use lg != nil to indicate whether user choose to use zap or plog. Before deprecating plog, we cannot simply provide a no-op lg in the top level, right? I think we can keep the lg != nil check in this PR. Later when we deprecate plog, we will remove lg != nil everywhere.

@gyuho
Copy link
Contributor

gyuho commented Feb 3, 2020

@jingyih Sounds good. Let's just keep it that way for now.

@YoyinZyc
Copy link
Contributor Author

Rebased the current master and removed the lg != nil check. Tests will be added in the following PR to keep a relative small size of this PR. PHAL.
The failed e2e test seems like a flaky test and it passed locally on my machine.

=== RUN   TestIssue6361
--- FAIL: TestIssue6361 (14.81s)
    ctl_v3_snapshot_test.go:262: read /dev/ptmx: input/output error (expected "val1", got ["{\"level\":\"warn\",\"ts\":\"2020-02-19T23:19:34.677Z\",\"caller\":\"clientv3/retry_interceptor.go:61\",\"msg\":\"retrying of unary invoker failed\",\"target\":\"endpoint://client-6cb9466f-d07c-40ff-bf75-24beea447b31/localhost:20030\",\"attempt\":0,\"error\":\"rpc error: code = DeadlineExceeded desc = context deadline exceeded\"}\r\n" "Error: context deadline exceeded\r\n"])
=== RUN   TestIssue6361
--- PASS: TestIssue6361 (11.27s)

@YoyinZyc YoyinZyc requested a review from gyuho February 20, 2020 00:04
@YoyinZyc
Copy link
Contributor Author

YoyinZyc commented Mar 9, 2020

@jpbetz Could you please also take a look? Thanks
cc @lavalamp

@YoyinZyc YoyinZyc mentioned this pull request Mar 23, 2020
13 tasks
@stale
Copy link

stale bot commented Jun 7, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 7, 2020
@spzala spzala removed the stale label Jun 7, 2020
@stale
Copy link

stale bot commented Sep 5, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Sep 5, 2020
@stale stale bot closed this Sep 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

4 participants