From adae7a659ecabb5f99366f6bc94cae51a4decd3c Mon Sep 17 00:00:00 2001 From: Danielle Lancashire Date: Thu, 17 Mar 2022 15:48:01 +0000 Subject: [PATCH] tests/framework: Add User operations --- tests/framework/config/client.go | 4 ++ tests/framework/e2e/etcdctl.go | 87 ++++++++++++++++++++++++++++++++ tests/framework/integration.go | 22 ++++++++ tests/framework/interface.go | 5 ++ 4 files changed, 118 insertions(+) diff --git a/tests/framework/config/client.go b/tests/framework/config/client.go index ef2ef9c27..ffbd8825a 100644 --- a/tests/framework/config/client.go +++ b/tests/framework/config/client.go @@ -54,3 +54,7 @@ type DefragOption struct { type LeaseOption struct { WithAttachedKeys bool } + +type UserAddOptions struct { + NoPassword bool +} diff --git a/tests/framework/e2e/etcdctl.go b/tests/framework/e2e/etcdctl.go index dd5f57e35..d7629c2fb 100644 --- a/tests/framework/e2e/etcdctl.go +++ b/tests/framework/e2e/etcdctl.go @@ -375,3 +375,90 @@ func (ctl *EtcdctlV3) AlarmDisarm(_ *clientv3.AlarmMember) (*clientv3.AlarmRespo err = json.Unmarshal([]byte(line), &resp) return &resp, err } + +func (ctl *EtcdctlV3) UserAdd(name, password string, opts config.UserAddOptions) (*clientv3.AuthUserAddResponse, error) { + args := ctl.cmdArgs() + args = append(args, "user", "add") + if password == "" { + args = append(args, name) + } else { + args = append(args, fmt.Sprintf("%s:%s", name, password)) + } + + if opts.NoPassword { + args = append(args, "--no-password") + } + + args = append(args, "--interactive=false", "-w", "json") + + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + + // If no password is provided, and NoPassword isn't set, the CLI will always + // wait for a password, send an enter in this case for an "empty" password. + if !opts.NoPassword && password == "" { + err := cmd.Send("\n") + if err != nil { + return nil, err + } + } + + var resp clientv3.AuthUserAddResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) UserList() (*clientv3.AuthUserListResponse, error) { + args := ctl.cmdArgs() + args = append(args, "user", "list", "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.AuthUserListResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error) { + args := ctl.cmdArgs() + args = append(args, "user", "delete", name, "-w", "json") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return nil, err + } + var resp clientv3.AuthUserDeleteResponse + line, err := cmd.Expect("header") + if err != nil { + return nil, err + } + err = json.Unmarshal([]byte(line), &resp) + return &resp, err +} + +func (ctl *EtcdctlV3) UserChangePass(user, newPass string) error { + args := ctl.cmdArgs() + args = append(args, "user", "passwd", user, "--interactive=false") + cmd, err := SpawnCmd(args, nil) + if err != nil { + return err + } + + err = cmd.Send(newPass + "\n") + if err != nil { + return err + } + + _, err = cmd.Expect("Password updated") + return err +} diff --git a/tests/framework/integration.go b/tests/framework/integration.go index f5867da46..38bca9618 100644 --- a/tests/framework/integration.go +++ b/tests/framework/integration.go @@ -259,3 +259,25 @@ func (c integrationClient) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevo return c.Client.Revoke(ctx, id) } + +func (c integrationClient) UserAdd(name, password string, opts config.UserAddOptions) (*clientv3.AuthUserAddResponse, error) { + ctx := context.Background() + return c.Client.UserAddWithOptions(ctx, name, password, &clientv3.UserAddOptions{ + NoPassword: opts.NoPassword, + }) +} + +func (c integrationClient) UserList() (*clientv3.AuthUserListResponse, error) { + ctx := context.Background() + return c.Client.UserList(ctx) +} + +func (c integrationClient) UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error) { + ctx := context.Background() + return c.Client.UserDelete(ctx, name) +} + +func (c integrationClient) UserChangePass(user, newPass string) error { + _, err := c.Client.UserChangePassword(context.Background(), user, newPass) + return err +} diff --git a/tests/framework/interface.go b/tests/framework/interface.go index 8460483dd..55e51d58c 100644 --- a/tests/framework/interface.go +++ b/tests/framework/interface.go @@ -48,4 +48,9 @@ type Client interface { LeaseList() (*clientv3.LeaseLeasesResponse, error) LeaseKeepAliveOnce(id clientv3.LeaseID) (*clientv3.LeaseKeepAliveResponse, error) LeaseRevoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeResponse, error) + + UserAdd(name, password string, opts config.UserAddOptions) (*clientv3.AuthUserAddResponse, error) + UserList() (*clientv3.AuthUserListResponse, error) + UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error) + UserChangePass(user, newPass string) error }