Repository: etcd-io/etcd
File: tests/e2e/etcd_release_upgrade_test.go (Go)

Code before:
	require.NoError(t, ctlV3Get(cx, []string{kvs[0].key}, []kv{kvs[0]}...))
}

func TestClusterUpgradeAfterPromotingMembers(t *testing.T) {
	if !fileutil.Exist(e2e.BinPath.EtcdLastRelease) {
		t.Skipf("%q does not exist", e2e.BinPath.EtcdLastRelease)
	}

	e2e.BeforeTest(t)

	currentVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.Etcd)
	require.NoErrorf(t, err, "failed to get version from binary")

	lastClusterVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.EtcdLastRelease)
	require.NoErrorf(t, err, "failed to get version from last release binary")

	epc := createNewClusterByPromotingMembers(t, e2e.LastVersion)
	defer func() {
		require.NoError(t, epc.Close())
	}()

	err = e2e.DowngradeUpgradeMembers(t, nil, epc, 3, false, lastClusterVersion, currentVersion)
	require.NoError(t, err)
}

func createNewClusterByPromotingMembers(t *testing.T, clusterVersion e2e.ClusterVersion) *e2e.EtcdProcessCluster {
	var version *semver.Version
	var err error

	switch clusterVersion {
	case e2e.CurrentVersion:
		version, err = e2e.GetVersionFromBinary(e2e.BinPath.Etcd)
		require.NoErrorf(t, err, "failed to get version from binary")
	case e2e.LastVersion:
		if !fileutil.Exist(e2e.BinPath.EtcdLastRelease) {
			t.Skipf("%q does not exist", e2e.BinPath.EtcdLastRelease)
		}

		version, err = e2e.GetVersionFromBinary(e2e.BinPath.EtcdLastRelease)
		require.NoErrorf(t, err, "failed to get version from last release binary")
	default:
		t.Fatalf("unexpected cluster version: %v", clusterVersion)
	}

	t.Logf("Creating new etcd cluster - %v", version)

	t.Log("Creating first node")
	epc, err := e2e.NewEtcdProcessCluster(t.Context(), t,
		e2e.WithVersion(clusterVersion),
		e2e.WithClusterSize(1),
		e2e.WithSnapshotCount(10),

Review comment (suggestion):
I think we can add one more parameter `clusterSize int`. The first member is always a voting member, and adding all other members as learner one by one.

Code after:

	require.NoError(t, ctlV3Get(cx, []string{kvs[0].key}, []kv{kvs[0]}...))
}

func TestClusterUpgradeAfterPromotingMembers(t *testing.T) {
	if !fileutil.Exist(e2e.BinPath.EtcdLastRelease) {
		t.Skipf("%q does not exist", e2e.BinPath.EtcdLastRelease)
	}

	e2e.BeforeTest(t)

	currentVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.Etcd)
	require.NoErrorf(t, err, "failed to get version from binary")

	lastClusterVersion, err := e2e.GetVersionFromBinary(e2e.BinPath.EtcdLastRelease)
	require.NoErrorf(t, err, "failed to get version from last release binary")

	clusterSize := 3

	for _, tc := range []struct {
		name     string
		snapshot int
	}{
		{
			name:     "create snapshot after promoted",
			snapshot: 10,
		},
		{
			name: "no snapshot after promoted",
		},
	} {
		t.Run(tc.name, func(t *testing.T) {
			ctx := context.Background()

			epc, _ := mustCreateNewClusterByPromotingMembers(t, e2e.LastVersion, clusterSize,
				e2e.WithSnapshotCount(uint64(tc.snapshot)))
			defer func() {
				require.NoError(t, epc.Close())
			}()

			for i := 0; i < tc.snapshot; i++ {
				err = epc.Etcdctl().Put(ctx, "foo", "bar", config.PutOptions{})
				require.NoError(t, err)
			}

			err = e2e.DowngradeUpgradeMembers(t, nil, epc, clusterSize, false, lastClusterVersion, currentVersion)
			require.NoError(t, err)

			t.Logf("Checking all members' status after upgrading")
			ensureAllMembersAreVotingMembers(t, epc)