mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #9404 from jpbetz/automated-cherry-pick-of-#9379-origin-release-3.2
Automated cherry pick of #9379
This commit is contained in:
commit
58f9080f60
@ -15,9 +15,13 @@
|
|||||||
package e2e
|
package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
epb "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb"
|
||||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||||
"github.com/coreos/etcd/pkg/testutil"
|
"github.com/coreos/etcd/pkg/testutil"
|
||||||
|
|
||||||
@ -162,3 +166,204 @@ func TestV3CurlTxn(t *testing.T) {
|
|||||||
t.Fatalf("failed put with curl (%v)", err)
|
t.Fatalf("failed put with curl (%v)", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestV3CurlAuthAlpha(t *testing.T) { testV3CurlAuth(t, "/v3alpha") }
|
||||||
|
func TestV3CurlAuthBeta(t *testing.T) { testV3CurlAuth(t, "/v3beta") }
|
||||||
|
func testV3CurlAuth(t *testing.T, pathPrefix string) {
|
||||||
|
defer testutil.AfterTest(t)
|
||||||
|
epc, err := newEtcdProcessCluster(&configNoTLS)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not start etcd process cluster (%v)", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if cerr := epc.Close(); err != nil {
|
||||||
|
t.Fatalf("error closing etcd processes (%v)", cerr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// create root user
|
||||||
|
userreq, err := json.Marshal(&pb.AuthUserAddRequest{Name: string("root"), Password: string("toor")})
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/user/add"), value: string(userreq), expected: "revision"}); err != nil {
|
||||||
|
t.Fatalf("failed add user with curl (%v)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create root role
|
||||||
|
rolereq, err := json.Marshal(&pb.AuthRoleAddRequest{Name: string("root")})
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/role/add"), value: string(rolereq), expected: "revision"}); err != nil {
|
||||||
|
t.Fatalf("failed create role with curl (%v)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// grant root role
|
||||||
|
grantrolereq, err := json.Marshal(&pb.AuthUserGrantRoleRequest{User: string("root"), Role: string("root")})
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/user/grant"), value: string(grantrolereq), expected: "revision"}); err != nil {
|
||||||
|
t.Fatalf("failed grant role with curl (%v)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable auth
|
||||||
|
if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/auth/enable"), value: string("{}"), expected: "revision"}); err != nil {
|
||||||
|
t.Fatalf("failed enable auth with curl (%v)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// put "bar" into "foo"
|
||||||
|
putreq, err := json.Marshal(&pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")})
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
// fail put no auth
|
||||||
|
if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/put"), value: string(putreq), expected: "error"}); err != nil {
|
||||||
|
t.Fatalf("failed no auth put with curl (%v)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// auth request
|
||||||
|
authreq, err := json.Marshal(&pb.AuthenticateRequest{Name: string("root"), Password: string("toor")})
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
var (
|
||||||
|
authHeader string
|
||||||
|
cmdArgs []string
|
||||||
|
lineFunc = func(txt string) bool { return true }
|
||||||
|
)
|
||||||
|
|
||||||
|
cmdArgs = cURLPrefixArgs(epc, "POST", cURLReq{endpoint: path.Join(pathPrefix, "/auth/authenticate"), value: string(authreq)})
|
||||||
|
proc, err := spawnCmd(cmdArgs)
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
cURLRes, err := proc.ExpectFunc(lineFunc)
|
||||||
|
testutil.AssertNil(t, err)
|
||||||
|
|
||||||
|
authRes := make(map[string]interface{})
|
||||||
|
testutil.AssertNil(t, json.Unmarshal([]byte(cURLRes), &authRes))
|
||||||
|
|
||||||
|
token, ok := authRes["token"].(string)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("failed invalid token in authenticate response with curl")
|
||||||
|
}
|
||||||
|
|
||||||
|
authHeader = "Authorization : " + token
|
||||||
|
|
||||||
|
// put with auth
|
||||||
|
if err = cURLPost(epc, cURLReq{endpoint: path.Join(pathPrefix, "/kv/put"), value: string(putreq), header: authHeader, expected: "revision"}); err != nil {
|
||||||
|
t.Fatalf("failed auth put with curl (%v)", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestV3CurlCampaignAlpha(t *testing.T) { testV3CurlCampaign(t, "/v3alpha") }
|
||||||
|
func TestV3CurlCampaignBeta(t *testing.T) { testV3CurlCampaign(t, "/v3beta") }
|
||||||
|
func testV3CurlCampaign(t *testing.T, pathPrefix string) {
|
||||||
|
defer testutil.AfterTest(t)
|
||||||
|
|
||||||
|
epc, err := newEtcdProcessCluster(&configNoTLS)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not start etcd process cluster (%v)", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if cerr := epc.Close(); err != nil {
|
||||||
|
t.Fatalf("error closing etcd processes (%v)", cerr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
cdata, err := json.Marshal(&epb.CampaignRequest{
|
||||||
|
Name: []byte("/election-prefix"),
|
||||||
|
Value: []byte("v1"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cargs := cURLPrefixArgs(epc, "POST", cURLReq{
|
||||||
|
endpoint: path.Join(pathPrefix, "/election/campaign"),
|
||||||
|
value: string(cdata),
|
||||||
|
})
|
||||||
|
lines, err := spawnWithExpectLines(cargs, `"leader":{"name":"`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed post campaign request (%s) (%v)", pathPrefix, err)
|
||||||
|
}
|
||||||
|
if len(lines) != 1 {
|
||||||
|
t.Fatalf("len(lines) expected 1, got %+v", lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cresp campaignResponse
|
||||||
|
if err = json.Unmarshal([]byte(lines[0]), &cresp); err != nil {
|
||||||
|
t.Fatalf("failed to unmarshal campaign response %v", err)
|
||||||
|
}
|
||||||
|
ndata, err := base64.StdEncoding.DecodeString(cresp.Leader.Name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to decode leader key %v", err)
|
||||||
|
}
|
||||||
|
kdata, err := base64.StdEncoding.DecodeString(cresp.Leader.Key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to decode leader key %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rev, _ := strconv.ParseInt(cresp.Leader.Rev, 10, 64)
|
||||||
|
lease, _ := strconv.ParseInt(cresp.Leader.Lease, 10, 64)
|
||||||
|
pdata, err := json.Marshal(&epb.ProclaimRequest{
|
||||||
|
Leader: &epb.LeaderKey{
|
||||||
|
Name: ndata,
|
||||||
|
Key: kdata,
|
||||||
|
Rev: rev,
|
||||||
|
Lease: lease,
|
||||||
|
},
|
||||||
|
Value: []byte("v2"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = cURLPost(epc, cURLReq{
|
||||||
|
endpoint: path.Join(pathPrefix, "/election/proclaim"),
|
||||||
|
value: string(pdata),
|
||||||
|
expected: `"revision":`,
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("failed post proclaim request (%s) (%v)", pathPrefix, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestV3CurlProclaimMissiongLeaderKeyNoTLS(t *testing.T) {
|
||||||
|
testCtl(t, testV3CurlProclaimMissiongLeaderKey, withCfg(configNoTLS))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testV3CurlProclaimMissiongLeaderKey(cx ctlCtx) {
|
||||||
|
pdata, err := json.Marshal(&epb.ProclaimRequest{Value: []byte("v2")})
|
||||||
|
if err != nil {
|
||||||
|
cx.t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
cx.t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = cURLPost(cx.epc, cURLReq{
|
||||||
|
endpoint: path.Join("/v3beta", "/election/proclaim"),
|
||||||
|
value: string(pdata),
|
||||||
|
expected: `{"error":"\"leader\" field must be provided","code":2}`,
|
||||||
|
}); err != nil {
|
||||||
|
cx.t.Fatalf("failed post proclaim request (%s) (%v)", "/v3beta", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestV3CurlResignMissiongLeaderKeyNoTLS(t *testing.T) {
|
||||||
|
testCtl(t, testV3CurlResignMissiongLeaderKey, withCfg(configNoTLS))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testV3CurlResignMissiongLeaderKey(cx ctlCtx) {
|
||||||
|
if err := cURLPost(cx.epc, cURLReq{
|
||||||
|
endpoint: path.Join("/v3beta", "/election/resign"),
|
||||||
|
value: `{}`,
|
||||||
|
expected: `{"error":"\"leader\" field must be provided","code":2}`,
|
||||||
|
}); err != nil {
|
||||||
|
cx.t.Fatalf("failed post resign request (%s) (%v)", "/v3beta", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// to manually decode; JSON marshals integer fields with
|
||||||
|
// string types, so can't unmarshal with epb.CampaignResponse
|
||||||
|
type campaignResponse struct {
|
||||||
|
Leader struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Rev string `json:"rev,omitempty"`
|
||||||
|
Lease string `json:"lease,omitempty"`
|
||||||
|
} `json:"leader,omitempty"`
|
||||||
|
}
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
package v3election
|
package v3election
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"github.com/coreos/etcd/clientv3"
|
"github.com/coreos/etcd/clientv3"
|
||||||
@ -22,6 +24,10 @@ import (
|
|||||||
epb "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb"
|
epb "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrMissingLeaderKey is returned when election API request
|
||||||
|
// is missing the "leader" field.
|
||||||
|
var ErrMissingLeaderKey = errors.New(`"leader" field must be provided`)
|
||||||
|
|
||||||
type electionServer struct {
|
type electionServer struct {
|
||||||
c *clientv3.Client
|
c *clientv3.Client
|
||||||
}
|
}
|
||||||
@ -51,6 +57,9 @@ func (es *electionServer) Campaign(ctx context.Context, req *epb.CampaignRequest
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (es *electionServer) Proclaim(ctx context.Context, req *epb.ProclaimRequest) (*epb.ProclaimResponse, error) {
|
func (es *electionServer) Proclaim(ctx context.Context, req *epb.ProclaimRequest) (*epb.ProclaimResponse, error) {
|
||||||
|
if req.Leader == nil {
|
||||||
|
return nil, ErrMissingLeaderKey
|
||||||
|
}
|
||||||
s, err := es.session(ctx, req.Leader.Lease)
|
s, err := es.session(ctx, req.Leader.Lease)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -98,6 +107,9 @@ func (es *electionServer) Leader(ctx context.Context, req *epb.LeaderRequest) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (es *electionServer) Resign(ctx context.Context, req *epb.ResignRequest) (*epb.ResignResponse, error) {
|
func (es *electionServer) Resign(ctx context.Context, req *epb.ResignRequest) (*epb.ResignResponse, error) {
|
||||||
|
if req.Leader == nil {
|
||||||
|
return nil, ErrMissingLeaderKey
|
||||||
|
}
|
||||||
s, err := es.session(ctx, req.Leader.Lease)
|
s, err := es.session(ctx, req.Leader.Lease)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user