diff --git a/cli/exp_scaletest.go b/cli/exp_scaletest.go index 4580ff3e1b..9f032b2070 100644 --- a/cli/exp_scaletest.go +++ b/cli/exp_scaletest.go @@ -32,11 +32,11 @@ import ( "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/workspacesdk" - "github.com/coder/coder/v2/cryptorand" "github.com/coder/coder/v2/scaletest/agentconn" "github.com/coder/coder/v2/scaletest/createworkspaces" "github.com/coder/coder/v2/scaletest/dashboard" "github.com/coder/coder/v2/scaletest/harness" + "github.com/coder/coder/v2/scaletest/loadtestutil" "github.com/coder/coder/v2/scaletest/reconnectingpty" "github.com/coder/coder/v2/scaletest/workspacebuild" "github.com/coder/coder/v2/scaletest/workspacetraffic" @@ -647,16 +647,6 @@ func (r *RootCmd) scaletestCreateWorkspaces() *serpent.Command { if useHostUser { config.User.SessionToken = client.SessionToken() - } else { - config.User.Username, config.User.Email, err = newScaleTestUser(id) - if err != nil { - return xerrors.Errorf("create scaletest username and email: %w", err) - } - } - - config.Workspace.Request.Name, err = newScaleTestWorkspace(id) - if err != nil { - return xerrors.Errorf("create scaletest workspace name: %w", err) } if runCommand != "" { @@ -1408,31 +1398,6 @@ func (r *runnableTraceWrapper) Cleanup(ctx context.Context, id string, logs io.W return c.Cleanup(ctx, id, logs) } -// newScaleTestUser returns a random username and email address that can be used -// for scale testing. The returned username is prefixed with "scaletest-" and -// the returned email address is suffixed with "@scaletest.local". -func newScaleTestUser(id string) (username string, email string, err error) { - randStr, err := cryptorand.String(8) - return fmt.Sprintf("scaletest-%s-%s", randStr, id), fmt.Sprintf("%s-%s@scaletest.local", randStr, id), err -} - -// newScaleTestWorkspace returns a random workspace name that can be used for -// scale testing. The returned workspace name is prefixed with "scaletest-" and -// suffixed with the given id. -func newScaleTestWorkspace(id string) (name string, err error) { - randStr, err := cryptorand.String(8) - return fmt.Sprintf("scaletest-%s-%s", randStr, id), err -} - -func isScaleTestUser(user codersdk.User) bool { - return strings.HasSuffix(user.Email, "@scaletest.local") -} - -func isScaleTestWorkspace(workspace codersdk.Workspace) bool { - return strings.HasPrefix(workspace.OwnerName, "scaletest-") || - strings.HasPrefix(workspace.Name, "scaletest-") -} - func getScaletestWorkspaces(ctx context.Context, client *codersdk.Client, owner, template string) ([]codersdk.Workspace, int, error) { var ( pageNumber = 0 @@ -1471,7 +1436,7 @@ func getScaletestWorkspaces(ctx context.Context, client *codersdk.Client, owner, pageWorkspaces := make([]codersdk.Workspace, 0, len(page.Workspaces)) for _, w := range page.Workspaces { - if !isScaleTestWorkspace(w) { + if !loadtestutil.IsScaleTestWorkspace(w.Name, w.OwnerName) { continue } if noOwnerAccess && w.OwnerID != me.ID { @@ -1511,7 +1476,7 @@ func getScaletestUsers(ctx context.Context, client *codersdk.Client) ([]codersdk pageUsers := make([]codersdk.User, 0, len(page.Users)) for _, u := range page.Users { - if isScaleTestUser(u) { + if loadtestutil.IsScaleTestUser(u.Username, u.Email) { pageUsers = append(pageUsers, u) } } diff --git a/scaletest/createworkspaces/config.go b/scaletest/createworkspaces/config.go index 579d9b5288..bd6a81b2ba 100644 --- a/scaletest/createworkspaces/config.go +++ b/scaletest/createworkspaces/config.go @@ -13,9 +13,9 @@ import ( type UserConfig struct { // OrganizationID is the ID of the organization to add the user to. OrganizationID uuid.UUID `json:"organization_id"` - // Username is the username of the new user. + // Username is the username of the new user. Generated if empty. Username string `json:"username"` - // Email is the email of the new user. + // Email is the email of the new user. Generated if empty. Email string `json:"email"` // SessionToken is the session token of an already existing user. If set, no // user will be created. @@ -26,12 +26,12 @@ func (c UserConfig) Validate() error { if c.OrganizationID == uuid.Nil { return xerrors.New("organization_id must not be a nil UUID") } - if c.SessionToken == "" { - if c.Username == "" { - return xerrors.New("username must be set") + if c.SessionToken != "" { + if c.Username != "" { + return xerrors.New("username must be empty when session_token is set") } - if c.Email == "" { - return xerrors.New("email must be set") + if c.Email != "" { + return xerrors.New("email must be empty when session_token is set") } } diff --git a/scaletest/createworkspaces/config_test.go b/scaletest/createworkspaces/config_test.go index 3965e9f9df..4dffd36c8b 100644 --- a/scaletest/createworkspaces/config_test.go +++ b/scaletest/createworkspaces/config_test.go @@ -43,22 +43,29 @@ func Test_UserConfig(t *testing.T) { errContains: "organization_id must not be a nil UUID", }, { - name: "NoUsername", + name: "OKSessionToken", config: createworkspaces.UserConfig{ OrganizationID: id, - Username: "", - Email: "test@test.coder.com", + SessionToken: "sometoken", }, - errContains: "username must be set", }, { - name: "NoEmail", + name: "WithSessionTokenAndUsername", config: createworkspaces.UserConfig{ OrganizationID: id, Username: "test", - Email: "", + SessionToken: "sometoken", }, - errContains: "email must be set", + errContains: "username must be empty when session_token is set", + }, + { + name: "WithSessionTokenAndEmail", + config: createworkspaces.UserConfig{ + OrganizationID: id, + Email: "test@test.coder.com", + SessionToken: "sometoken", + }, + errContains: "email must be empty when session_token is set", }, } diff --git a/scaletest/loadtestutil/names.go b/scaletest/loadtestutil/names.go new file mode 100644 index 0000000000..f29ded1578 --- /dev/null +++ b/scaletest/loadtestutil/names.go @@ -0,0 +1,55 @@ +package loadtestutil + +import ( + "fmt" + "strings" + + "github.com/coder/coder/v2/cryptorand" +) + +const ( + // Prefix for all scaletest resources (users and workspaces) + ScaleTestPrefix = "scaletest" + + // Email domain for scaletest users + EmailDomain = "@scaletest.local" + + DefaultRandLength = 8 +) + +// GenerateUserIdentifier generates a username and email for scale testing. +// The username follows the pattern: scaletest-- +// The email follows the pattern: -@scaletest.local +func GenerateUserIdentifier(id string) (username, email string, err error) { + randStr, err := cryptorand.String(DefaultRandLength) + if err != nil { + return "", "", err + } + + username = fmt.Sprintf("%s-%s-%s", ScaleTestPrefix, randStr, id) + email = fmt.Sprintf("%s-%s%s", randStr, id, EmailDomain) + return username, email, nil +} + +// GenerateWorkspaceName generates a workspace name for scale testing. +// The workspace name follows the pattern: scaletest-- +func GenerateWorkspaceName(id string) (name string, err error) { + randStr, err := cryptorand.String(DefaultRandLength) + if err != nil { + return "", err + } + + return fmt.Sprintf("%s-%s-%s", ScaleTestPrefix, randStr, id), nil +} + +// IsScaleTestUser checks if a username indicates it was created for scale testing. +func IsScaleTestUser(username, email string) bool { + return strings.HasPrefix(username, ScaleTestPrefix+"-") || + strings.HasSuffix(email, EmailDomain) +} + +// IsScaleTestWorkspace checks if a workspace name indicates it was created for scale testing. +func IsScaleTestWorkspace(workspaceName, ownerName string) bool { + return strings.HasPrefix(workspaceName, ScaleTestPrefix+"-") || + strings.HasPrefix(ownerName, ScaleTestPrefix+"-") +} diff --git a/scaletest/workspacebuild/run.go b/scaletest/workspacebuild/run.go index 3b369a4e48..5b8c2c3237 100644 --- a/scaletest/workspacebuild/run.go +++ b/scaletest/workspacebuild/run.go @@ -15,7 +15,6 @@ import ( "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/codersdk" - "github.com/coder/coder/v2/cryptorand" "github.com/coder/coder/v2/scaletest/harness" "github.com/coder/coder/v2/scaletest/loadtestutil" ) @@ -40,7 +39,7 @@ func NewRunner(client *codersdk.Client, cfg Config) *Runner { } // Run implements Runnable. -func (r *Runner) Run(ctx context.Context, _ string, logs io.Writer) error { +func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error { ctx, span := tracing.StartSpan(ctx) defer span.End() @@ -51,11 +50,11 @@ func (r *Runner) Run(ctx context.Context, _ string, logs io.Writer) error { req := r.cfg.Request if req.Name == "" { - randName, err := cryptorand.HexString(8) + randName, err := loadtestutil.GenerateWorkspaceName(id) if err != nil { return xerrors.Errorf("generate random name for workspace: %w", err) } - req.Name = "test-" + randName + req.Name = randName } workspace, err := r.client.CreateWorkspace(ctx, r.cfg.OrganizationID, r.cfg.UserID, req)