feat(scaletest): allow scaletests to run using the host credentials (#7075)

This commit is contained in:
Colin Adler
2023-04-11 14:49:28 -05:00
committed by GitHub
parent 2585249014
commit a44070e2ec
6 changed files with 93 additions and 54 deletions

View File

@ -471,7 +471,7 @@ func (r *RootCmd) scaletestCleanup() *clibase.Cmd {
} }
cliui.Errorf(inv.Stderr, "Found %d scaletest users\n", len(users)) cliui.Errorf(inv.Stderr, "Found %d scaletest users\n", len(users))
if len(workspaces) != 0 { if len(users) != 0 {
cliui.Infof(inv.Stdout, "Deleting scaletest users..."+"\n") cliui.Infof(inv.Stdout, "Deleting scaletest users..."+"\n")
harness := harness.NewTestHarness(cleanupStrategy.toStrategy(), harness.ConcurrentExecutionStrategy{}) harness := harness.NewTestHarness(cleanupStrategy.toStrategy(), harness.ConcurrentExecutionStrategy{})
@ -535,6 +535,8 @@ func (r *RootCmd) scaletestCreateWorkspaces() *clibase.Cmd {
connectInterval time.Duration connectInterval time.Duration
connectTimeout time.Duration connectTimeout time.Duration
useHostUser bool
tracingFlags = &scaletestTracingFlags{} tracingFlags = &scaletestTracingFlags{}
strategy = &scaletestStrategyFlags{} strategy = &scaletestStrategyFlags{}
cleanupStrategy = &scaletestStrategyFlags{cleanup: true} cleanupStrategy = &scaletestStrategyFlags{cleanup: true}
@ -693,28 +695,16 @@ func (r *RootCmd) scaletestCreateWorkspaces() *clibase.Cmd {
const name = "workspacebuild" const name = "workspacebuild"
id := strconv.Itoa(i) id := strconv.Itoa(i)
username, email, err := newScaleTestUser(id)
if err != nil {
return xerrors.Errorf("create scaletest username and email: %w", err)
}
workspaceName, err := newScaleTestWorkspace(id)
if err != nil {
return xerrors.Errorf("create scaletest workspace name: %w", err)
}
config := createworkspaces.Config{ config := createworkspaces.Config{
User: createworkspaces.UserConfig{ User: createworkspaces.UserConfig{
// TODO: configurable org // TODO: configurable org
OrganizationID: me.OrganizationIDs[0], OrganizationID: me.OrganizationIDs[0],
Username: username,
Email: email,
}, },
Workspace: workspacebuild.Config{ Workspace: workspacebuild.Config{
OrganizationID: me.OrganizationIDs[0], OrganizationID: me.OrganizationIDs[0],
// UserID is set by the test automatically. // UserID is set by the test automatically.
Request: codersdk.CreateWorkspaceRequest{ Request: codersdk.CreateWorkspaceRequest{
TemplateID: tpl.ID, TemplateID: tpl.ID,
Name: workspaceName,
ParameterValues: params, ParameterValues: params,
}, },
NoWaitForAgents: noWaitForAgents, NoWaitForAgents: noWaitForAgents,
@ -722,6 +712,20 @@ func (r *RootCmd) scaletestCreateWorkspaces() *clibase.Cmd {
NoCleanup: noCleanup, NoCleanup: noCleanup,
} }
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 != "" { if runCommand != "" {
config.ReconnectingPTY = &reconnectingpty.Config{ config.ReconnectingPTY = &reconnectingpty.Config{
// AgentID is set by the test automatically. // AgentID is set by the test automatically.
@ -927,6 +931,13 @@ func (r *RootCmd) scaletestCreateWorkspaces() *clibase.Cmd {
Description: "Timeout for each request to the --connect-url.", Description: "Timeout for each request to the --connect-url.",
Value: clibase.DurationOf(&connectTimeout), Value: clibase.DurationOf(&connectTimeout),
}, },
{
Flag: "use-host-login",
Env: "CODER_SCALETEST_USE_HOST_LOGIN",
Default: "false",
Description: "Use the use logged in on the host machine, instead of creating users.",
Value: clibase.BoolOf(&useHostUser),
},
} }
tracingFlags.attach(&cmd.Options) tracingFlags.attach(&cmd.Options)
@ -1009,9 +1020,6 @@ func isScaleTestUser(user codersdk.User) bool {
} }
func isScaleTestWorkspace(workspace codersdk.Workspace) bool { func isScaleTestWorkspace(workspace codersdk.Workspace) bool {
if !strings.HasPrefix(workspace.OwnerName, "scaletest-") { return strings.HasPrefix(workspace.OwnerName, "scaletest-") ||
return false strings.HasPrefix(workspace.Name, "scaletest-")
}
return strings.HasPrefix(workspace.Name, "scaletest-")
} }

View File

@ -116,5 +116,8 @@ It is recommended that all rate limits are disabled on the server before running
if the server is configured with the exact same tracing configuration if the server is configured with the exact same tracing configuration
as the client. as the client.
--use-host-login bool, $CODER_SCALETEST_USE_HOST_LOGIN (default: false)
Use the use logged in on the host machine, instead of creating users.
--- ---
Run `coder --help` for a list of global options. Run `coder --help` for a list of global options.

View File

@ -490,14 +490,14 @@ func (server *Server) UpdateJob(ctx context.Context, request *proto.UpdateJobReq
slog.F("stage", log.Stage), slog.F("stage", log.Stage),
slog.F("output", log.Output)) slog.F("output", log.Output))
} }
//nolint:gocritic // Provisionerd has specific authz rules.
logs, err := server.Database.InsertProvisionerJobLogs(dbauthz.AsProvisionerd(context.Background()), insertParams) logs, err := server.Database.InsertProvisionerJobLogs(ctx, insertParams)
if err != nil { if err != nil {
server.Logger.Error(ctx, "failed to insert job logs", slog.F("job_id", parsedID), slog.Error(err)) server.Logger.Error(ctx, "failed to insert job logs", slog.F("job_id", parsedID), slog.Error(err))
return nil, xerrors.Errorf("insert job logs: %w", err) return nil, xerrors.Errorf("insert job logs: %w", err)
} }
// Publish by the lowest log ID inserted so the // Publish by the lowest log ID inserted so the log stream will fetch
// log stream will fetch everything from that point. // everything from that point.
lowestID := logs[0].ID lowestID := logs[0].ID
server.Logger.Debug(ctx, "inserted job logs", slog.F("job_id", parsedID)) server.Logger.Debug(ctx, "inserted job logs", slog.F("job_id", parsedID))
data, err := json.Marshal(ProvisionerJobLogsNotifyMessage{ data, err := json.Marshal(ProvisionerJobLogsNotifyMessage{

View File

@ -282,3 +282,13 @@ Enables trace exporting to Honeycomb.io using the provided API key.
| Environment | <code>$CODER_SCALETEST_TRACE_PROPAGATE</code> | | Environment | <code>$CODER_SCALETEST_TRACE_PROPAGATE</code> |
Enables trace propagation to the Coder backend, which will be used to correlate server-side spans with client-side spans. Only enable this if the server is configured with the exact same tracing configuration as the client. Enables trace propagation to the Coder backend, which will be used to correlate server-side spans with client-side spans. Only enable this if the server is configured with the exact same tracing configuration as the client.
### --use-host-login
| | |
| ----------- | -------------------------------------------- |
| Type | <code>bool</code> |
| Environment | <code>$CODER_SCALETEST_USE_HOST_LOGIN</code> |
| Default | <code>false</code> |
Use the use logged in on the host machine, instead of creating users.

View File

@ -17,6 +17,9 @@ type UserConfig struct {
Username string `json:"username"` Username string `json:"username"`
// Email is the email of the new user. // Email is the email of the new user.
Email string `json:"email"` Email string `json:"email"`
// SessionToken is the session token of an already existing user. If set, no
// user will be created.
SessionToken string `json:"session_token"`
} }
func (c UserConfig) Validate() error { func (c UserConfig) Validate() error {

View File

@ -52,6 +52,18 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
r.client.Logger = logger r.client.Logger = logger
r.client.LogBodies = true r.client.LogBodies = true
var (
client = r.client
user codersdk.User
err error
)
if r.cfg.User.SessionToken != "" {
_, _ = fmt.Fprintln(logs, "Using existing user session token:")
user, err = client.User(ctx, "me")
if err != nil {
return xerrors.Errorf("generate random password for user: %w", err)
}
} else {
_, _ = fmt.Fprintln(logs, "Generating user password...") _, _ = fmt.Fprintln(logs, "Generating user password...")
password, err := cryptorand.String(16) password, err := cryptorand.String(16)
if err != nil { if err != nil {
@ -59,10 +71,7 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
} }
_, _ = fmt.Fprintln(logs, "Creating user:") _, _ = fmt.Fprintln(logs, "Creating user:")
_, _ = fmt.Fprintf(logs, "\tOrg ID: %s\n", r.cfg.User.OrganizationID.String())
_, _ = fmt.Fprintf(logs, "\tUsername: %s\n", r.cfg.User.Username)
_, _ = fmt.Fprintf(logs, "\tEmail: %s\n", r.cfg.User.Email)
_, _ = fmt.Fprintf(logs, "\tPassword: ****************\n")
user, err := r.client.CreateUser(ctx, codersdk.CreateUserRequest{ user, err := r.client.CreateUser(ctx, codersdk.CreateUserRequest{
OrganizationID: r.cfg.User.OrganizationID, OrganizationID: r.cfg.User.OrganizationID,
Username: r.cfg.User.Username, Username: r.cfg.User.Username,
@ -75,21 +84,27 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
r.userID = user.ID r.userID = user.ID
_, _ = fmt.Fprintln(logs, "\nLogging in as new user...") _, _ = fmt.Fprintln(logs, "\nLogging in as new user...")
userClient := codersdk.New(r.client.URL) client = codersdk.New(r.client.URL)
loginRes, err := userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{ loginRes, err := client.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
Email: r.cfg.User.Email, Email: r.cfg.User.Email,
Password: password, Password: password,
}) })
if err != nil { if err != nil {
return xerrors.Errorf("login as new user: %w", err) return xerrors.Errorf("login as new user: %w", err)
} }
userClient.SetSessionToken(loginRes.SessionToken) client.SetSessionToken(loginRes.SessionToken)
}
_, _ = fmt.Fprintf(logs, "\tOrg ID: %s\n", r.cfg.User.OrganizationID.String())
_, _ = fmt.Fprintf(logs, "\tUsername: %s\n", user.Username)
_, _ = fmt.Fprintf(logs, "\tEmail: %s\n", user.Email)
_, _ = fmt.Fprintf(logs, "\tPassword: ****************\n")
_, _ = fmt.Fprintln(logs, "\nCreating workspace...") _, _ = fmt.Fprintln(logs, "\nCreating workspace...")
workspaceBuildConfig := r.cfg.Workspace workspaceBuildConfig := r.cfg.Workspace
workspaceBuildConfig.OrganizationID = r.cfg.User.OrganizationID workspaceBuildConfig.OrganizationID = r.cfg.User.OrganizationID
workspaceBuildConfig.UserID = user.ID.String() workspaceBuildConfig.UserID = user.ID.String()
r.workspacebuildRunner = workspacebuild.NewRunner(userClient, workspaceBuildConfig) r.workspacebuildRunner = workspacebuild.NewRunner(client, workspaceBuildConfig)
err = r.workspacebuildRunner.Run(ctx, id, logs) err = r.workspacebuildRunner.Run(ctx, id, logs)
if err != nil { if err != nil {
return xerrors.Errorf("create workspace: %w", err) return xerrors.Errorf("create workspace: %w", err)
@ -104,7 +119,7 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
if err != nil { if err != nil {
return xerrors.Errorf("get workspace ID: %w", err) return xerrors.Errorf("get workspace ID: %w", err)
} }
workspace, err := userClient.Workspace(ctx, workspaceID) workspace, err := client.Workspace(ctx, workspaceID)
if err != nil { if err != nil {
return xerrors.Errorf("get workspace %q: %w", workspaceID.String(), err) return xerrors.Errorf("get workspace %q: %w", workspaceID.String(), err)
} }
@ -128,7 +143,7 @@ resourceLoop:
reconnectingPTYConfig := *r.cfg.ReconnectingPTY reconnectingPTYConfig := *r.cfg.ReconnectingPTY
reconnectingPTYConfig.AgentID = agent.ID reconnectingPTYConfig.AgentID = agent.ID
reconnectingPTYRunner := reconnectingpty.NewRunner(userClient, reconnectingPTYConfig) reconnectingPTYRunner := reconnectingpty.NewRunner(client, reconnectingPTYConfig)
err := reconnectingPTYRunner.Run(egCtx, id, logs) err := reconnectingPTYRunner.Run(egCtx, id, logs)
if err != nil { if err != nil {
return xerrors.Errorf("run reconnecting pty: %w", err) return xerrors.Errorf("run reconnecting pty: %w", err)
@ -142,7 +157,7 @@ resourceLoop:
agentConnConfig := *r.cfg.AgentConn agentConnConfig := *r.cfg.AgentConn
agentConnConfig.AgentID = agent.ID agentConnConfig.AgentID = agent.ID
agentConnRunner := agentconn.NewRunner(userClient, agentConnConfig) agentConnRunner := agentconn.NewRunner(client, agentConnConfig)
err := agentConnRunner.Run(egCtx, id, logs) err := agentConnRunner.Run(egCtx, id, logs)
if err != nil { if err != nil {
return xerrors.Errorf("run agent connection: %w", err) return xerrors.Errorf("run agent connection: %w", err)