From 79e3d7bd3eb67daa90f17fa40b5521ae8f3b1f28 Mon Sep 17 00:00:00 2001 From: Piotr Tabor Date: Wed, 12 May 2021 16:00:06 +0200 Subject: [PATCH] Add e2e tests for --v2-deprecation flag. --- tests/e2e/cluster_proxy_test.go | 9 +-- tests/e2e/cluster_test.go | 20 ++++-- tests/e2e/ctl_v3_migrate_test.go | 8 --- tests/e2e/ctl_v3_test.go | 2 +- tests/e2e/main_test.go | 14 +--- tests/e2e/testing.go | 38 +++++++++++ tests/e2e/v2store_deprecation_test.go | 98 +++++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 28 deletions(-) create mode 100644 tests/e2e/testing.go create mode 100644 tests/e2e/v2store_deprecation_test.go diff --git a/tests/e2e/cluster_proxy_test.go b/tests/e2e/cluster_proxy_test.go index 953e68946..7a5740d14 100644 --- a/tests/e2e/cluster_proxy_test.go +++ b/tests/e2e/cluster_proxy_test.go @@ -22,6 +22,7 @@ import ( "net" "net/url" "os" + "path" "strconv" "strings" @@ -268,10 +269,10 @@ func newProxyV3Proc(cfg *etcdServerProcessConfig) *proxyV3Proc { // Configure certificates for connection proxy ---> server. // This certificate must NOT have CN set. tlsArgs = append(tlsArgs, - "--cert", "../fixtures/client-nocn.crt", - "--key", "../fixtures/client-nocn.key.insecure", - "--cacert", "../fixtures/ca.crt", - "--client-crl-file", "../fixtures/revoke.crl") + "--cert", path.Join(fixturesDir, "client-nocn.crt"), + "--key", path.Join(fixturesDir, "client-nocn.key.insecure"), + "--cacert", path.Join(fixturesDir, "ca.crt"), + "--client-crl-file", path.Join(fixturesDir, "revoke.crl")) } return &proxyV3Proc{ proxyProc{ diff --git a/tests/e2e/cluster_test.go b/tests/e2e/cluster_test.go index 2a3298fb0..cc47121fa 100644 --- a/tests/e2e/cluster_test.go +++ b/tests/e2e/cluster_test.go @@ -18,17 +18,23 @@ import ( "fmt" "net/url" "os" + "path" "strings" "testing" "time" "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/tests/v3/integration" ) const etcdProcessBasePort = 20000 type clientConnType int +var ( + fixturesDir = integration.MustAbsPath("../fixtures") +) + const ( clientNonTLS clientConnType = iota clientTLS @@ -113,9 +119,10 @@ func newConfigClientTLSCertAuthWithNoCN() *etcdProcessClusterConfig { func newConfigJWT() *etcdProcessClusterConfig { return &etcdProcessClusterConfig{ - clusterSize: 1, - initialToken: "new", - authTokenOpts: "jwt,pub-key=../fixtures/server.crt,priv-key=../fixtures/server.key.insecure,sign-method=RS256,ttl=1s", + clusterSize: 1, + initialToken: "new", + authTokenOpts: "jwt,pub-key=" + path.Join(fixturesDir, "server.crt") + + ",priv-key=" + path.Join(fixturesDir, "server.key.insecure") + ",sign-method=RS256,ttl=1s", } } @@ -161,6 +168,7 @@ type etcdProcessClusterConfig struct { enableV2 bool initialCorruptCheck bool authTokenOpts string + v2deprecation string rollingStart bool } @@ -246,7 +254,7 @@ func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs(tb testing.TB) []* } purl := url.URL{Scheme: cfg.peerScheme(), Host: fmt.Sprintf("localhost:%d", port+1)} - name := fmt.Sprintf("test-%s-%d", tb.Name(), i) + name := fmt.Sprintf("test-%d", i) dataDirPath := cfg.dataDirPath if cfg.dataDirPath == "" { dataDirPath = tb.TempDir() @@ -296,6 +304,10 @@ func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs(tb testing.TB) []* args = append(args, "--auth-token", cfg.authTokenOpts) } + if cfg.v2deprecation != "" { + args = append(args, "--v2-deprecation", cfg.v2deprecation) + } + etcdCfgs[i] = &etcdServerProcessConfig{ execPath: cfg.execPath, args: args, diff --git a/tests/e2e/ctl_v3_migrate_test.go b/tests/e2e/ctl_v3_migrate_test.go index bdaeaf22b..c36b5a38c 100644 --- a/tests/e2e/ctl_v3_migrate_test.go +++ b/tests/e2e/ctl_v3_migrate_test.go @@ -21,17 +21,9 @@ import ( "testing" "time" - "go.etcd.io/etcd/client/pkg/v3/testutil" "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/server/v3/verify" ) -func BeforeTest(t testing.TB) { - skipInShortMode(t) - testutil.BeforeTest(t) - os.Setenv(verify.ENV_VERIFY, verify.ENV_VERIFY_ALL_VALUE) -} - func TestCtlV3Migrate(t *testing.T) { BeforeTest(t) diff --git a/tests/e2e/ctl_v3_test.go b/tests/e2e/ctl_v3_test.go index d1743e088..f6eeeecbf 100644 --- a/tests/e2e/ctl_v3_test.go +++ b/tests/e2e/ctl_v3_test.go @@ -30,7 +30,7 @@ import ( func TestCtlV3Version(t *testing.T) { testCtl(t, versionTest) } func TestClusterVersion(t *testing.T) { - skipInShortMode(t) + BeforeTest(t) tests := []struct { name string diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 75adb1e8e..ddb7ae4ba 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -6,13 +6,12 @@ package e2e import ( "flag" - "log" "os" - "path/filepath" "runtime" "testing" "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.etcd.io/etcd/tests/v3/integration" ) var ( @@ -38,15 +37,8 @@ func TestMain(m *testing.M) { os.Setenv("ETCD_UNSUPPORTED_ARCH", runtime.GOARCH) os.Unsetenv("ETCDCTL_API") - binDirDef, err := filepath.Abs("../../bin") - if err != nil { - log.Fatal(err) - } - - certDirDef, err := filepath.Abs("../fixtures") - if err != nil { - log.Fatal(err) - } + binDirDef := integration.MustAbsPath("../../bin") + certDirDef := fixturesDir flag.StringVar(&binDir, "bin-dir", binDirDef, "The directory for store etcd and etcdctl binaries.") flag.StringVar(&certDir, "cert-dir", certDirDef, "The directory for store certificate files.") diff --git a/tests/e2e/testing.go b/tests/e2e/testing.go new file mode 100644 index 000000000..a36c075db --- /dev/null +++ b/tests/e2e/testing.go @@ -0,0 +1,38 @@ +// Copyright 2021 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "go.etcd.io/etcd/client/pkg/v3/testutil" + "go.etcd.io/etcd/server/v3/verify" +) + +func BeforeTest(t testing.TB) { + skipInShortMode(t) + testutil.BeforeTest(t) + os.Setenv(verify.ENV_VERIFY, verify.ENV_VERIFY_ALL_VALUE) + + path, err := os.Getwd() + assert.NoError(t, err) + tempDir := t.TempDir() + assert.NoError(t, os.Chdir(tempDir)) + t.Logf("Changing working directory to: %s", tempDir) + + t.Cleanup(func() { assert.NoError(t, os.Chdir(path)) }) +} diff --git a/tests/e2e/v2store_deprecation_test.go b/tests/e2e/v2store_deprecation_test.go new file mode 100644 index 000000000..06ad555d0 --- /dev/null +++ b/tests/e2e/v2store_deprecation_test.go @@ -0,0 +1,98 @@ +// Copyright 2016 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func createV2store(t testing.TB, dataDirPath string) { + t.Log("Creating not-yet v2-deprecated etcd") + + cfg := configStandalone(etcdProcessClusterConfig{enableV2: true, dataDirPath: dataDirPath, snapshotCount: 5}) + epc, err := newEtcdProcessCluster(t, cfg) + assert.NoError(t, err) + + defer func() { + assert.NoError(t, epc.Stop()) + }() + + // We need to exceed 'snapshotCount' such that v2 snapshot is dumped. + for i := 0; i < 10; i++ { + if err := cURLPut(epc, cURLReq{ + endpoint: "/v2/keys/foo", value: "bar" + fmt.Sprint(i), + expected: `{"action":"set","node":{"key":"/foo","value":"bar` + fmt.Sprint(i)}); err != nil { + t.Fatalf("failed put with curl (%v)", err) + } + } +} + +func assertVerifyCanStartV2deprecationNotYet(t testing.TB, dataDirPath string) { + t.Log("verify: possible to start etcd with --v2-deprecation=not-yet mode") + + cfg := configStandalone(etcdProcessClusterConfig{enableV2: true, dataDirPath: dataDirPath, v2deprecation: "not-yet", keepDataDir: true}) + epc, err := newEtcdProcessCluster(t, cfg) + assert.NoError(t, err) + + defer func() { + assert.NoError(t, epc.Stop()) + }() + + if err := cURLGet(epc, cURLReq{ + endpoint: "/v2/keys/foo", + expected: `{"action":"get","node":{"key":"/foo","value":"bar9","modifiedIndex":13,"createdIndex":13}}`}); err != nil { + t.Fatalf("failed get with curl (%v)", err) + } + +} + +func assertVerifyCannotStartV2deprecationWriteOnly(t testing.TB, dataDirPath string) { + t.Log("Verify its infeasible to start etcd with --v2-deprecation=write-only mode") + proc, err := spawnCmd([]string{binDir + "/etcd", "--v2-deprecation=write-only", "--data-dir=" + dataDirPath}) + assert.NoError(t, err) + + _, err = proc.Expect("detected disallowed custom content in v2store for stage --v2-deprecation=write-only") + assert.NoError(t, err) +} + +func TestV2Deprecation(t *testing.T) { + BeforeTest(t) + dataDirPath := t.TempDir() + + t.Run("create-storev2-data", func(t *testing.T) { + createV2store(t, dataDirPath) + }) + + t.Run("--v2-deprecation=write-only fails", func(t *testing.T) { + assertVerifyCannotStartV2deprecationWriteOnly(t, dataDirPath) + }) + + t.Run("--v2-deprecation=not-yet succeeds", func(t *testing.T) { + assertVerifyCanStartV2deprecationNotYet(t, dataDirPath) + }) + +} + +func TestV2DeprecationWriteOnlyNoV2Api(t *testing.T) { + BeforeTest(t) + proc, err := spawnCmd([]string{binDir + "/etcd", "--v2-deprecation=write-only", "--enable-v2"}) + assert.NoError(t, err) + + _, err = proc.Expect("--enable-v2 and --v2-deprecation=write-only are mutually exclusive") + assert.NoError(t, err) +}