mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
fix: use is-dormant instead of dormant_at (#10191)
This commit is contained in:
@@ -6818,12 +6818,11 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
|
||||
}
|
||||
|
||||
// We omit locked workspaces by default.
|
||||
if arg.DormantAt.IsZero() && workspace.DormantAt.Valid {
|
||||
if arg.IsDormant == "" && workspace.DormantAt.Valid {
|
||||
continue
|
||||
}
|
||||
|
||||
// Filter out workspaces that are locked after the timestamp.
|
||||
if !arg.DormantAt.IsZero() && workspace.DormantAt.Time.Before(arg.DormantAt) {
|
||||
if arg.IsDormant != "" && !workspace.DormantAt.Valid {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
|
||||
arg.Name,
|
||||
arg.HasAgent,
|
||||
arg.AgentInactiveDisconnectTimeoutSeconds,
|
||||
arg.DormantAt,
|
||||
arg.IsDormant,
|
||||
arg.LastUsedBefore,
|
||||
arg.LastUsedAfter,
|
||||
arg.Offset,
|
||||
|
||||
@@ -10160,8 +10160,8 @@ WHERE
|
||||
-- Filter by dormant workspaces. By default we do not return dormant
|
||||
-- workspaces since they are considered soft-deleted.
|
||||
AND CASE
|
||||
WHEN $10 :: timestamptz > '0001-01-01 00:00:00+00'::timestamptz THEN
|
||||
dormant_at IS NOT NULL AND dormant_at >= $10
|
||||
WHEN $10 :: text != '' THEN
|
||||
dormant_at IS NOT NULL
|
||||
ELSE
|
||||
dormant_at IS NULL
|
||||
END
|
||||
@@ -10204,7 +10204,7 @@ type GetWorkspacesParams struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
HasAgent string `db:"has_agent" json:"has_agent"`
|
||||
AgentInactiveDisconnectTimeoutSeconds int64 `db:"agent_inactive_disconnect_timeout_seconds" json:"agent_inactive_disconnect_timeout_seconds"`
|
||||
DormantAt time.Time `db:"dormant_at" json:"dormant_at"`
|
||||
IsDormant string `db:"is_dormant" json:"is_dormant"`
|
||||
LastUsedBefore time.Time `db:"last_used_before" json:"last_used_before"`
|
||||
LastUsedAfter time.Time `db:"last_used_after" json:"last_used_after"`
|
||||
Offset int32 `db:"offset_" json:"offset_"`
|
||||
@@ -10243,7 +10243,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
|
||||
arg.Name,
|
||||
arg.HasAgent,
|
||||
arg.AgentInactiveDisconnectTimeoutSeconds,
|
||||
arg.DormantAt,
|
||||
arg.IsDormant,
|
||||
arg.LastUsedBefore,
|
||||
arg.LastUsedAfter,
|
||||
arg.Offset,
|
||||
|
||||
@@ -242,8 +242,8 @@ WHERE
|
||||
-- Filter by dormant workspaces. By default we do not return dormant
|
||||
-- workspaces since they are considered soft-deleted.
|
||||
AND CASE
|
||||
WHEN @dormant_at :: timestamptz > '0001-01-01 00:00:00+00'::timestamptz THEN
|
||||
dormant_at IS NOT NULL AND dormant_at >= @dormant_at
|
||||
WHEN @is_dormant :: text != '' THEN
|
||||
dormant_at IS NOT NULL
|
||||
ELSE
|
||||
dormant_at IS NULL
|
||||
END
|
||||
|
||||
@@ -8,13 +8,14 @@ import (
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/sqlc-dev/pqtype"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtime"
|
||||
"github.com/coder/coder/v2/coderd/externalauth"
|
||||
"github.com/coder/coder/v2/coderd/httpapi"
|
||||
"github.com/coder/coder/v2/coderd/httpmw"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/sqlc-dev/pqtype"
|
||||
)
|
||||
|
||||
// @Summary Get external auth by ID
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/httpapi"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
@@ -70,11 +69,7 @@ func Users(query string) (database.GetUsersParams, []codersdk.ValidationError) {
|
||||
return filter, parser.Errors
|
||||
}
|
||||
|
||||
type PostFilter struct {
|
||||
DeletingBy *time.Time `json:"deleting_by" format:"date-time"`
|
||||
}
|
||||
|
||||
func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectTimeout time.Duration) (database.GetWorkspacesParams, PostFilter, []codersdk.ValidationError) {
|
||||
func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectTimeout time.Duration) (database.GetWorkspacesParams, []codersdk.ValidationError) {
|
||||
filter := database.GetWorkspacesParams{
|
||||
AgentInactiveDisconnectTimeoutSeconds: int64(agentInactiveDisconnectTimeout.Seconds()),
|
||||
|
||||
@@ -82,10 +77,8 @@ func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectT
|
||||
Limit: int32(page.Limit),
|
||||
}
|
||||
|
||||
var postFilter PostFilter
|
||||
|
||||
if query == "" {
|
||||
return filter, postFilter, nil
|
||||
return filter, nil
|
||||
}
|
||||
|
||||
// Always lowercase for all searches.
|
||||
@@ -105,7 +98,7 @@ func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectT
|
||||
return nil
|
||||
})
|
||||
if len(errors) > 0 {
|
||||
return filter, postFilter, errors
|
||||
return filter, errors
|
||||
}
|
||||
|
||||
parser := httpapi.NewQueryParamParser()
|
||||
@@ -114,21 +107,12 @@ func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectT
|
||||
filter.Name = parser.String(values, "", "name")
|
||||
filter.Status = string(httpapi.ParseCustom(parser, values, "", "status", httpapi.ParseEnum[database.WorkspaceStatus]))
|
||||
filter.HasAgent = parser.String(values, "", "has-agent")
|
||||
filter.DormantAt = parser.Time(values, time.Time{}, "dormant_at", "2006-01-02")
|
||||
filter.IsDormant = parser.String(values, "", "is-dormant")
|
||||
filter.LastUsedAfter = parser.Time3339Nano(values, time.Time{}, "last_used_after")
|
||||
filter.LastUsedBefore = parser.Time3339Nano(values, time.Time{}, "last_used_before")
|
||||
|
||||
if _, ok := values["deleting_by"]; ok {
|
||||
postFilter.DeletingBy = ptr.Ref(parser.Time(values, time.Time{}, "deleting_by", "2006-01-02"))
|
||||
// We want to make sure to grab dormant workspaces since they
|
||||
// are omitted by default.
|
||||
if filter.DormantAt.IsZero() {
|
||||
filter.DormantAt = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
}
|
||||
|
||||
parser.ErrorExcessParams(values)
|
||||
return filter, postFilter, parser.Errors
|
||||
return filter, parser.Errors
|
||||
}
|
||||
|
||||
func searchTerms(query string, defaultKey func(term string, values url.Values) error) (url.Values, []codersdk.ValidationError) {
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/coderd/searchquery"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
@@ -150,7 +149,7 @@ func TestSearchWorkspace(t *testing.T) {
|
||||
c := c
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
values, postFilter, errs := searchquery.Workspaces(c.Query, codersdk.Pagination{}, 0)
|
||||
values, errs := searchquery.Workspaces(c.Query, codersdk.Pagination{}, 0)
|
||||
if c.ExpectedErrorContains != "" {
|
||||
assert.True(t, len(errs) > 0, "expect some errors")
|
||||
var s strings.Builder
|
||||
@@ -159,7 +158,6 @@ func TestSearchWorkspace(t *testing.T) {
|
||||
}
|
||||
assert.Contains(t, s.String(), c.ExpectedErrorContains)
|
||||
} else {
|
||||
assert.Empty(t, postFilter)
|
||||
assert.Len(t, errs, 0, "expected no error")
|
||||
assert.Equal(t, c.Expected, values, "expected values")
|
||||
}
|
||||
@@ -170,51 +168,10 @@ func TestSearchWorkspace(t *testing.T) {
|
||||
|
||||
query := ``
|
||||
timeout := 1337 * time.Second
|
||||
values, _, errs := searchquery.Workspaces(query, codersdk.Pagination{}, timeout)
|
||||
values, errs := searchquery.Workspaces(query, codersdk.Pagination{}, timeout)
|
||||
require.Empty(t, errs)
|
||||
require.Equal(t, int64(timeout.Seconds()), values.AgentInactiveDisconnectTimeoutSeconds)
|
||||
})
|
||||
|
||||
t.Run("TestSearchWorkspacePostFilter", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Query string
|
||||
Expected searchquery.PostFilter
|
||||
}{
|
||||
{
|
||||
Name: "Empty",
|
||||
Query: "",
|
||||
Expected: searchquery.PostFilter{},
|
||||
},
|
||||
{
|
||||
Name: "DeletingBy",
|
||||
Query: "deleting_by:2023-06-09",
|
||||
Expected: searchquery.PostFilter{
|
||||
DeletingBy: ptr.Ref(time.Date(
|
||||
2023, 6, 9, 0, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MultipleParams",
|
||||
Query: "deleting_by:2023-06-09 name:workspace-name",
|
||||
Expected: searchquery.PostFilter{
|
||||
DeletingBy: ptr.Ref(time.Date(
|
||||
2023, 6, 9, 0, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
c := c
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, postFilter, errs := searchquery.Workspaces(c.Query, codersdk.Pagination{}, 0)
|
||||
assert.Len(t, errs, 0, "expected no error")
|
||||
assert.Equal(t, c.Expected, postFilter, "expected values")
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchAudit(t *testing.T) {
|
||||
|
||||
+2
-20
@@ -131,7 +131,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
queryStr := r.URL.Query().Get("q")
|
||||
filter, postFilter, errs := searchquery.Workspaces(queryStr, page, api.AgentInactiveDisconnectTimeout)
|
||||
filter, errs := searchquery.Workspaces(queryStr, page, api.AgentInactiveDisconnectTimeout)
|
||||
if len(errs) > 0 {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid workspace search query.",
|
||||
@@ -191,26 +191,8 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var filteredWorkspaces []codersdk.Workspace
|
||||
// apply post filters, if they exist
|
||||
if postFilter.DeletingBy == nil {
|
||||
filteredWorkspaces = append(filteredWorkspaces, wss...)
|
||||
} else {
|
||||
for _, v := range wss {
|
||||
if v.DeletingAt == nil {
|
||||
continue
|
||||
}
|
||||
// get the beginning of the day on which deletion is scheduled
|
||||
truncatedDeletionAt := time.Date(v.DeletingAt.Year(), v.DeletingAt.Month(), v.DeletingAt.Day(), 0, 0, 0, 0, v.DeletingAt.Location())
|
||||
if truncatedDeletionAt.After(*postFilter.DeletingBy) {
|
||||
continue
|
||||
}
|
||||
filteredWorkspaces = append(filteredWorkspaces, v)
|
||||
}
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, codersdk.WorkspacesResponse{
|
||||
Workspaces: filteredWorkspaces,
|
||||
Workspaces: wss,
|
||||
Count: int(workspaceRows[0].Count),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -1395,63 +1394,7 @@ func TestWorkspaceFilterManual(t *testing.T) {
|
||||
}, testutil.IntervalMedium, "agent status timeout")
|
||||
})
|
||||
|
||||
t.Run("FilterQueryHasDeletingByAndUnlicensed", func(t *testing.T) {
|
||||
// this test has a licensed counterpart in enterprise/coderd/workspaces_test.go: FilterQueryHasDeletingByAndLicensed
|
||||
t.Parallel()
|
||||
inactivityTTL := 1 * 24 * time.Hour
|
||||
var setCalled int64
|
||||
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
TemplateScheduleStore: schedule.MockTemplateScheduleStore{
|
||||
SetFn: func(ctx context.Context, db database.Store, template database.Template, options schedule.TemplateScheduleOptions) (database.Template, error) {
|
||||
if atomic.AddInt64(&setCalled, 1) == 2 {
|
||||
assert.Equal(t, inactivityTTL, options.TimeTilDormant)
|
||||
}
|
||||
template.TimeTilDormant = int64(options.TimeTilDormant)
|
||||
return template, nil
|
||||
},
|
||||
},
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
authToken := uuid.NewString()
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionPlan: echo.PlanComplete,
|
||||
ProvisionApply: echo.ProvisionApplyWithAgent(authToken),
|
||||
})
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
|
||||
// update template with inactivity ttl
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
template, err := client.UpdateTemplateMeta(ctx, template.ID, codersdk.UpdateTemplateMeta{
|
||||
TimeTilDormantMillis: inactivityTTL.Milliseconds(),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, inactivityTTL.Milliseconds(), template.TimeTilDormantMillis)
|
||||
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
// stop build so workspace is inactive
|
||||
stopBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop)
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, stopBuild.ID)
|
||||
|
||||
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
|
||||
FilterQuery: fmt.Sprintf("deleting_by:%s", time.Now().Add(inactivityTTL).Format("2006-01-02")),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
// we are expecting that no workspaces are returned as user is unlicensed
|
||||
// and template.TimeTilDormant should be 0
|
||||
assert.Len(t, res.Workspaces, 0)
|
||||
})
|
||||
|
||||
t.Run("DormantAt", func(t *testing.T) {
|
||||
t.Run("IsDormant", func(t *testing.T) {
|
||||
// this test has a licensed counterpart in enterprise/coderd/workspaces_test.go: FilterQueryHasDeletingByAndLicensed
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
@@ -1484,7 +1427,7 @@ func TestWorkspaceFilterManual(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
|
||||
FilterQuery: fmt.Sprintf("dormant_at:%s", time.Now().Add(-time.Minute).Format("2006-01-02")),
|
||||
FilterQuery: "is-dormant:true",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.Workspaces, 1)
|
||||
|
||||
@@ -3,7 +3,6 @@ package coderd_test
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
@@ -17,7 +16,6 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/autobuild"
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
||||
agplschedule "github.com/coder/coder/v2/coderd/schedule"
|
||||
"github.com/coder/coder/v2/coderd/schedule/cron"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
@@ -741,61 +739,56 @@ func TestWorkspaceAutobuild(t *testing.T) {
|
||||
func TestWorkspacesFiltering(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("DeletingBy", func(t *testing.T) {
|
||||
t.Run("IsDormant", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dormantTTL := 24 * time.Hour
|
||||
|
||||
// nolint:gocritic // https://github.com/coder/coder/issues/9682
|
||||
db, ps := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC"))
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
client, user := coderdenttest.New(t, &coderdenttest.Options{
|
||||
Options: &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
Database: db,
|
||||
Pubsub: ps,
|
||||
TemplateScheduleStore: schedule.NewEnterpriseTemplateScheduleStore(agplUserQuietHoursScheduleStore()),
|
||||
},
|
||||
LicenseOptions: &coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
codersdk.FeatureAdvancedTemplateScheduling: 1,
|
||||
},
|
||||
Features: license.Features{codersdk.FeatureAdvancedTemplateScheduling: 1},
|
||||
},
|
||||
})
|
||||
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
// Create a template version that passes to get a functioning workspace.
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionPlan: echo.PlanComplete,
|
||||
ProvisionApply: echo.ApplyComplete,
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
// update template with inactivity ttl
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
dormantWS1 := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, dormantWS1.LatestBuild.ID)
|
||||
|
||||
template, err := client.UpdateTemplateMeta(ctx, template.ID, codersdk.UpdateTemplateMeta{
|
||||
TimeTilDormantAutoDeleteMillis: dormantTTL.Milliseconds(),
|
||||
dormantWS2 := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, dormantWS2.LatestBuild.ID)
|
||||
|
||||
activeWS := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, activeWS.LatestBuild.ID)
|
||||
|
||||
err := client.UpdateWorkspaceDormancy(ctx, dormantWS1.ID, codersdk.UpdateWorkspaceDormancy{Dormant: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = client.UpdateWorkspaceDormancy(ctx, dormantWS2.ID, codersdk.UpdateWorkspaceDormancy{Dormant: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
|
||||
FilterQuery: "is-dormant:true",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dormantTTL.Milliseconds(), template.TimeTilDormantAutoDeleteMillis)
|
||||
require.Len(t, resp.Workspaces, 2)
|
||||
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
_ = coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
// stop build so workspace is inactive
|
||||
stopBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop)
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, stopBuild.ID)
|
||||
err = client.UpdateWorkspaceDormancy(ctx, workspace.ID, codersdk.UpdateWorkspaceDormancy{
|
||||
Dormant: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
workspace = coderdtest.MustWorkspace(t, client, workspace.ID)
|
||||
require.NotNil(t, workspace.DeletingAt)
|
||||
|
||||
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
|
||||
// adding a second to time.Now() to give some buffer in case test runs quickly
|
||||
FilterQuery: fmt.Sprintf("deleting_by:%s", time.Now().Add(time.Second).Add(dormantTTL).Format("2006-01-02")),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.Workspaces, 1)
|
||||
require.Equal(t, workspace.ID, res.Workspaces[0].ID)
|
||||
for _, ws := range resp.Workspaces {
|
||||
if ws.ID != dormantWS1.ID && ws.ID != dormantWS2.ID {
|
||||
t.Fatalf("Unexpected workspace %+v", ws)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -88,10 +88,7 @@ export const DormantWorkspaceBanner = ({
|
||||
) : (
|
||||
<>
|
||||
<span>There are</span>{" "}
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to="/workspaces?filter=dormant_at:1970-01-01"
|
||||
>
|
||||
<Link component={RouterLink} to="/workspaces?filter=is-dormant:true">
|
||||
workspaces
|
||||
</Link>{" "}
|
||||
that may be deleted soon due to inactivity. Activate the workspaces
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ export const useWorkspacesToBeDeleted = (
|
||||
const { data } = useWorkspacesData({
|
||||
page: 0,
|
||||
limit: 0,
|
||||
query: "template:" + template.name + " dormant_at:1970-01-01",
|
||||
query: "template:" + template.name + " is-dormant:true",
|
||||
});
|
||||
return data?.workspaces?.filter((workspace: Workspace) => {
|
||||
if (!workspace.dormant_at || !formValues.time_til_dormant_autodelete_ms) {
|
||||
|
||||
@@ -68,10 +68,10 @@ const WorkspacesPage: FC = () => {
|
||||
// are at risk of being deleted.
|
||||
useEffect(() => {
|
||||
if (schedulingEnabled) {
|
||||
const includesDormant = filterProps.filter.query.includes("dormant_at");
|
||||
const includesDormant = filterProps.filter.query.includes("is-dormant");
|
||||
const dormantQuery = includesDormant
|
||||
? filterProps.filter.query
|
||||
: filterProps.filter.query + " dormant_at:1970-01-01";
|
||||
: filterProps.filter.query + " is-dormant:true";
|
||||
|
||||
if (includesDormant && data) {
|
||||
setDormantWorkspaces(data.workspaces);
|
||||
|
||||
@@ -17,7 +17,7 @@ export const workspaceFilterQuery = {
|
||||
all: "",
|
||||
running: "status:running",
|
||||
failed: "status:failed",
|
||||
dormant: "dormant_at:1970-01-01",
|
||||
dormant: "is-dormant:true",
|
||||
};
|
||||
|
||||
export const userFilterQuery = {
|
||||
|
||||
Reference in New Issue
Block a user