Skip to content

Commit

Permalink
e2e: add tests for issue 5182
Browse files Browse the repository at this point in the history
For #5182.
  • Loading branch information
gyuho committed Apr 26, 2016
1 parent 41ac5a3 commit 467ce0e
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 47 deletions.
8 changes: 6 additions & 2 deletions e2e/ctl_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ func testCtlV2Watch(t *testing.T, cfg *etcdProcessClusterConfig, noSync bool) {

func TestCtlV2GetRoleUser(t *testing.T) { testCtlV2GetRoleUser(t, &configNoTLS) }
func TestCtlV2GetRoleUserWithProxy(t *testing.T) { testCtlV2GetRoleUser(t, &configWithProxy) }

func testCtlV2GetRoleUser(t *testing.T, cfg *etcdProcessClusterConfig) {
defer testutil.AfterTest(t)

Expand All @@ -181,6 +180,7 @@ func testCtlV2GetRoleUser(t *testing.T, cfg *etcdProcessClusterConfig) {
if err := etcdctlUserGet(epc, "username"); err != nil {
t.Fatalf("failed to get user (%v)", err)
}

// ensure double grant gives an error; was crashing in 2.3.1
regrantArgs := etcdctlPrefixArgs(epc)
regrantArgs = append(regrantArgs, "user", "grant", "--roles", "foo", "username")
Expand All @@ -191,7 +191,6 @@ func testCtlV2GetRoleUser(t *testing.T, cfg *etcdProcessClusterConfig) {

func TestCtlV2UserListUsername(t *testing.T) { testCtlV2UserList(t, "username") }
func TestCtlV2UserListRoot(t *testing.T) { testCtlV2UserList(t, "root") }

func testCtlV2UserList(t *testing.T, username string) {
defer testutil.AfterTest(t)

Expand Down Expand Up @@ -325,6 +324,11 @@ func etcdctlUserList(clus *etcdProcessCluster, expectedUser string) error {
return spawnWithExpect(cmdArgs, expectedUser)
}

func etcdctlAuthEnable(clus *etcdProcessCluster) error {
cmdArgs := append(etcdctlPrefixArgs(clus), "auth", "enable")
return spawnWithExpect(cmdArgs, "Authentication Enabled")
}

func mustEtcdctl(t *testing.T) {
if !fileutil.Exist("../bin/etcdctl") {
t.Fatalf("could not find etcdctl binary")
Expand Down
146 changes: 101 additions & 45 deletions e2e/v2_curl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
package e2e

import (
"fmt"
"math/rand"
"strings"
"testing"

"github.com/coreos/etcd/pkg/testutil"
Expand All @@ -30,7 +32,6 @@ func TestV2CurlProxyNoTLS(t *testing.T) { testCurlPutGet(t, &configWithProxy)
func TestV2CurlProxyTLS(t *testing.T) { testCurlPutGet(t, &configWithProxyTLS) }
func TestV2CurlProxyPeerTLS(t *testing.T) { testCurlPutGet(t, &configWithProxyPeerTLS) }
func TestV2CurlClientBoth(t *testing.T) { testCurlPutGet(t, &configClientBoth) }

func testCurlPutGet(t *testing.T, cfg *etcdProcessClusterConfig) {
defer testutil.AfterTest(t)

Expand All @@ -48,66 +49,121 @@ func testCurlPutGet(t *testing.T, cfg *etcdProcessClusterConfig) {
}
}()

expectPut := `{"action":"set","node":{"key":"/testKey","value":"foo","`
expectGet := `{"action":"get","node":{"key":"/testKey","value":"foo","`

var (
expectPut = `{"action":"set","node":{"key":"/foo","value":"bar","`
expectGet = `{"action":"get","node":{"key":"/foo","value":"bar","`
)
if err := cURL(epc, cURLReq{method: "PUT", endpoint: "/v2/keys/foo", value: "bar", expected: expectPut}); err != nil {
t.Fatalf("failed put with curl (%v)", err)
}
if err := cURL(epc, cURLReq{method: "GET", endpoint: "/v2/keys/foo", expected: expectGet}); err != nil {
t.Fatalf("failed get with curl (%v)", err)
}
if cfg.clientTLS == clientTLSAndNonTLS {
if err := cURLPut(epc, "testKey", "foo", expectPut); err != nil {
t.Fatalf("failed put with curl (%v)", err)
}

if err := cURLGet(epc, "testKey", expectGet); err != nil {
if err := cURL(epc, cURLReq{method: "GET", endpoint: "/v2/keys/foo", expected: expectGet, isTLS: true}); err != nil {
t.Fatalf("failed get with curl (%v)", err)
}
if err := cURLGetUseTLS(epc, "testKey", expectGet); err != nil {
t.Fatalf("failed get with curl (%v)", err)
}
} else {
if err := cURLPut(epc, "testKey", "foo", expectPut); err != nil {
t.Fatalf("failed put with curl (%v)", err)
}
}

func TestV2CurlIssue5182(t *testing.T) {
defer testutil.AfterTest(t)

epc := setupEtcdctlTest(t, &configNoTLS, false)
defer func() {
if err := epc.Close(); err != nil {
t.Fatalf("error closing etcd processes (%v)", err)
}
}()

if err := cURLGet(epc, "testKey", expectGet); err != nil {
t.Fatalf("failed get with curl (%v)", err)
expectPut := `{"action":"set","node":{"key":"/foo","value":"bar","`
if err := cURL(epc, cURLReq{method: "PUT", endpoint: "/v2/keys/foo", value: "bar", expected: expectPut}); err != nil {
t.Fatal(err)
}

expectUserAdd := `{"user":"foo","roles":null}`
if err := cURL(epc, cURLReq{method: "PUT", endpoint: "/v2/auth/users/foo", value: `{"user":"foo", "password":"pass"}`, expected: expectUserAdd, isJSON: true}); err != nil {
t.Fatal(err)
}
expectRoleAdd := `{"role":"foo","permissions":{"kv":{"read":["/foo/*"],"write":null}}`
if err := cURL(epc, cURLReq{method: "PUT", endpoint: "/v2/auth/roles/foo", value: `{"role":"foo", "permissions": {"kv": {"read": ["/foo/*"]}}}`, expected: expectRoleAdd, isJSON: true}); err != nil {
t.Fatal(err)
}
expectUserUpdate := `{"user":"foo","roles":["foo"]}`
if err := cURL(epc, cURLReq{method: "PUT", endpoint: "/v2/auth/users/foo", value: `{"user": "foo", "grant": ["foo"]}`, expected: expectUserUpdate, isJSON: true}); err != nil {
t.Fatal(err)
}

if err := etcdctlUserAdd(epc, "root", "a"); err != nil {
t.Fatal(err)
}
if err := etcdctlAuthEnable(epc); err != nil {
t.Fatal(err)
}

if err := cURL(epc, cURLReq{method: "GET", endpoint: "/v2/keys/foo", username: "root", password: "a", expected: "bar"}); err != nil {
t.Fatal(err)
}
if err := cURL(epc, cURLReq{method: "GET", endpoint: "/v2/keys/foo/", username: "foo", password: "pass", expected: "bar"}); err != nil {
t.Fatal(err)
}
if err := cURL(epc, cURLReq{method: "GET", endpoint: "/v2/keys/foo/", username: "foo", password: "", expected: "bar"}); err != nil {
if !strings.Contains(err.Error(), `The request requires user authentication`) {
t.Fatalf("expected 'The request requires user authentication' error, got %v", err)
}
} else {
t.Fatalf("expected 'The request requires user authentication' error")
}
}

type cURLReq struct {
method string
endpoint string
username string
password string

isTLS bool
isJSON bool

value string
expected string
}

// cURLPrefixArgs builds the beginning of a curl command for a given key
// addressed to a random URL in the given cluster.
func cURLPrefixArgs(clus *etcdProcessCluster, key string) []string {
cmdArgs := []string{"curl"}
acurl := clus.procs[rand.Intn(clus.cfg.clusterSize)].cfg.acurl

if clus.cfg.clientTLS == clientTLS {
func cURLPrefixArgs(clus *etcdProcessCluster, req cURLReq) []string {
var (
cmdArgs = []string{"curl"}
acurl = clus.procs[rand.Intn(clus.cfg.clusterSize)].cfg.acurl
)
if req.isTLS {
if clus.cfg.clientTLS != clientTLSAndNonTLS {
panic("should not use cURLPrefixArgsUseTLS when serving only TLS or non-TLS")
}
cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
acurl = clus.procs[rand.Intn(clus.cfg.clusterSize)].cfg.acurltls
} else if clus.cfg.clientTLS == clientTLS {
cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
}
keyURL := acurl + "/v2/keys/testKey"
cmdArgs = append(cmdArgs, "-L", keyURL)
return cmdArgs
}
ep := acurl + req.endpoint

func cURLPrefixArgsUseTLS(clus *etcdProcessCluster, key string) []string {
cmdArgs := []string{"curl"}
if clus.cfg.clientTLS != clientTLSAndNonTLS {
panic("should not use cURLPrefixArgsUseTLS when serving only TLS or non-TLS")
if req.username != "" || req.password != "" {
cmdArgs = append(cmdArgs, "-L", "-u", fmt.Sprintf("%s:%s", req.username, req.password), ep)
} else {
cmdArgs = append(cmdArgs, "-L", ep)
}
cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
acurl := clus.procs[rand.Intn(clus.cfg.clusterSize)].cfg.acurltls
keyURL := acurl + "/v2/keys/testKey"
cmdArgs = append(cmdArgs, "-L", keyURL)
return cmdArgs
}

func cURLPut(clus *etcdProcessCluster, key, val, expected string) error {
args := append(cURLPrefixArgs(clus, key), "-XPUT", "-d", "value="+val)
return spawnWithExpect(args, expected)
}

func cURLGet(clus *etcdProcessCluster, key, expected string) error {
return spawnWithExpect(cURLPrefixArgs(clus, key), expected)
switch req.method {
case "PUT":
dt := req.value
if !req.isJSON {
dt = "value=" + dt
}
cmdArgs = append(cmdArgs, "-XPUT", "-d", dt)
}
return cmdArgs
}

func cURLGetUseTLS(clus *etcdProcessCluster, key, expected string) error {
return spawnWithExpect(cURLPrefixArgsUseTLS(clus, key), expected)
func cURL(clus *etcdProcessCluster, req cURLReq) error {
return spawnWithExpect(cURLPrefixArgs(clus, req), req.expected)
}

0 comments on commit 467ce0e

Please sign in to comment.