fix: fix workspace status filter returning more statuses that requested (#7732)

This commit is contained in:
Steven Masley
2023-06-05 18:12:10 -05:00
committed by GitHub
parent b9e3226612
commit fa8f50a169
6 changed files with 347 additions and 84 deletions

View File

@ -1168,82 +1168,68 @@ func (q *fakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
return nil, xerrors.Errorf("get provisioner job: %w", err)
}
// This logic should match the logic in the workspace.sql file.
var statusMatch bool
switch database.WorkspaceStatus(arg.Status) {
case database.WorkspaceStatusPending:
if !job.StartedAt.Valid {
continue
}
statusMatch = isNull(job.StartedAt)
case database.WorkspaceStatusStarting:
if !job.StartedAt.Valid &&
!job.CanceledAt.Valid &&
job.CompletedAt.Valid &&
time.Since(job.UpdatedAt) > 30*time.Second ||
build.Transition != database.WorkspaceTransitionStart {
continue
}
statusMatch = isNotNull(job.StartedAt) &&
isNull(job.CanceledAt) &&
isNull(job.CompletedAt) &&
time.Since(job.UpdatedAt) < 30*time.Second &&
build.Transition == database.WorkspaceTransitionStart
case database.WorkspaceStatusRunning:
if !job.CompletedAt.Valid &&
job.CanceledAt.Valid &&
job.Error.Valid ||
build.Transition != database.WorkspaceTransitionStart {
continue
}
statusMatch = isNotNull(job.CompletedAt) &&
isNull(job.CanceledAt) &&
isNull(job.Error) &&
build.Transition == database.WorkspaceTransitionStart
case database.WorkspaceStatusStopping:
if !job.StartedAt.Valid &&
!job.CanceledAt.Valid &&
job.CompletedAt.Valid &&
time.Since(job.UpdatedAt) > 30*time.Second ||
build.Transition != database.WorkspaceTransitionStop {
continue
}
statusMatch = isNotNull(job.StartedAt) &&
isNull(job.CanceledAt) &&
isNull(job.CompletedAt) &&
time.Since(job.UpdatedAt) < 30*time.Second &&
build.Transition == database.WorkspaceTransitionStop
case database.WorkspaceStatusStopped:
if !job.CompletedAt.Valid &&
job.CanceledAt.Valid &&
job.Error.Valid ||
build.Transition != database.WorkspaceTransitionStop {
continue
}
statusMatch = isNotNull(job.CompletedAt) &&
isNull(job.CanceledAt) &&
isNull(job.Error) &&
build.Transition == database.WorkspaceTransitionStop
case database.WorkspaceStatusFailed:
if (!job.CanceledAt.Valid && !job.Error.Valid) ||
(!job.CompletedAt.Valid && !job.Error.Valid) {
continue
}
statusMatch = (isNotNull(job.CanceledAt) && isNotNull(job.Error)) ||
(isNotNull(job.CompletedAt) && isNotNull(job.Error))
case database.WorkspaceStatusCanceling:
if !job.CanceledAt.Valid && job.CompletedAt.Valid {
continue
}
statusMatch = isNotNull(job.CanceledAt) &&
isNull(job.CompletedAt)
case database.WorkspaceStatusCanceled:
if !job.CanceledAt.Valid && !job.CompletedAt.Valid {
continue
}
statusMatch = isNotNull(job.CanceledAt) &&
isNotNull(job.CompletedAt)
case database.WorkspaceStatusDeleted:
if !job.StartedAt.Valid &&
job.CanceledAt.Valid &&
!job.CompletedAt.Valid &&
time.Since(job.UpdatedAt) > 30*time.Second ||
build.Transition != database.WorkspaceTransitionDelete {
continue
}
statusMatch = isNotNull(job.StartedAt) &&
isNull(job.CanceledAt) &&
isNotNull(job.CompletedAt) &&
time.Since(job.UpdatedAt) < 30*time.Second &&
build.Transition == database.WorkspaceTransitionDelete &&
isNull(job.Error)
case database.WorkspaceStatusDeleting:
if !job.CompletedAt.Valid &&
job.CanceledAt.Valid &&
job.Error.Valid &&
build.Transition != database.WorkspaceTransitionDelete {
continue
}
statusMatch = isNull(job.CompletedAt) &&
isNull(job.CanceledAt) &&
isNull(job.Error) &&
build.Transition == database.WorkspaceTransitionDelete
default:
return nil, xerrors.Errorf("unknown workspace status in filter: %q", arg.Status)
}
if !statusMatch {
continue
}
}
if arg.HasAgent != "" {
@ -5179,3 +5165,13 @@ func (q *fakeQuerier) UpdateWorkspaceProxyDeleted(_ context.Context, arg databas
}
return sql.ErrNoRows
}
// isNull is only used in dbfake, so reflect is ok. Use this to make the logic
// look more similar to the postgres.
func isNull(v interface{}) bool {
return !isNotNull(v)
}
func isNotNull(v interface{}) bool {
return reflect.ValueOf(v).FieldByName("Valid").Bool()
}