Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita106d67

Browse files
authored
feat(coderd): use task data model for list (#20394)
Updatescoder/internal#976
1 parent2c6cbf1 commita106d67

28 files changed

+976
-613
lines changed

‎cli/exp_task_delete.go‎

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"strings"
66
"time"
77

8-
"github.com/google/uuid"
98
"golang.org/x/xerrors"
109

1110
"github.com/coder/pretty"
@@ -47,43 +46,19 @@ func (r *RootCmd) taskDelete() *serpent.Command {
4746
}
4847
exp:=codersdk.NewExperimentalClient(client)
4948

50-
typetoDeletestruct {
51-
ID uuid.UUID
52-
Ownerstring
53-
Displaystring
54-
}
55-
56-
varitems []toDelete
49+
vartasks []codersdk.Task
5750
for_,identifier:=rangeinv.Args {
58-
identifier=strings.TrimSpace(identifier)
59-
ifidentifier=="" {
60-
returnxerrors.New("task identifier cannot be empty or whitespace")
61-
}
62-
63-
// Check task identifier, try UUID first.
64-
ifid,err:=uuid.Parse(identifier);err==nil {
65-
task,err:=exp.TaskByID(ctx,id)
66-
iferr!=nil {
67-
returnxerrors.Errorf("resolve task %q: %w",identifier,err)
68-
}
69-
display:=fmt.Sprintf("%s/%s",task.OwnerName,task.Name)
70-
items=append(items,toDelete{ID:id,Display:display,Owner:task.OwnerName})
71-
continue
72-
}
73-
74-
// Non-UUID, treat as a workspace identifier (name or owner/name).
75-
ws,err:=namedWorkspace(ctx,client,identifier)
51+
task,err:=exp.TaskByIdentifier(ctx,identifier)
7652
iferr!=nil {
7753
returnxerrors.Errorf("resolve task %q: %w",identifier,err)
7854
}
79-
display:=ws.FullName()
80-
items=append(items,toDelete{ID:ws.ID,Display:display,Owner:ws.OwnerName})
55+
tasks=append(tasks,task)
8156
}
8257

8358
// Confirm deletion of the tasks.
8459
vardisplayList []string
85-
for_,it:=rangeitems {
86-
displayList=append(displayList,it.Display)
60+
for_,task:=rangetasks {
61+
displayList=append(displayList,fmt.Sprintf("%s/%s",task.OwnerName,task.Name))
8762
}
8863
_,err=cliui.Prompt(inv, cliui.PromptOptions{
8964
Text:fmt.Sprintf("Delete these tasks: %s?",pretty.Sprint(cliui.DefaultStyles.Code,strings.Join(displayList,", "))),
@@ -94,12 +69,13 @@ func (r *RootCmd) taskDelete() *serpent.Command {
9469
returnerr
9570
}
9671

97-
for_,item:=rangeitems {
98-
iferr:=exp.DeleteTask(ctx,item.Owner,item.ID);err!=nil {
99-
returnxerrors.Errorf("delete task %q: %w",item.Display,err)
72+
fori,task:=rangetasks {
73+
display:=displayList[i]
74+
iferr:=exp.DeleteTask(ctx,task.OwnerName,task.ID);err!=nil {
75+
returnxerrors.Errorf("delete task %q: %w",display,err)
10076
}
10177
_,_=fmt.Fprintln(
102-
inv.Stdout,"Deleted task "+pretty.Sprint(cliui.DefaultStyles.Keyword,item.Display)+" at "+cliui.Timestamp(time.Now()),
78+
inv.Stdout,"Deleted task "+pretty.Sprint(cliui.DefaultStyles.Keyword,display)+" at "+cliui.Timestamp(time.Now()),
10379
)
10480
}
10581

‎cli/exp_task_delete_test.go‎

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,18 @@ func TestExpTaskDelete(t *testing.T) {
5656
taskID:=uuid.MustParse(id1)
5757
returnfunc(w http.ResponseWriter,r*http.Request) {
5858
switch {
59-
caser.Method==http.MethodGet&&r.URL.Path=="/api/v2/users/me/workspace/exists":
59+
caser.Method==http.MethodGet&&r.URL.Path=="/api/experimental/tasks"&&r.URL.Query().Get("q")=="owner:\"me\"":
6060
c.nameResolves.Add(1)
61-
httpapi.Write(r.Context(),w,http.StatusOK, codersdk.Workspace{
62-
ID:taskID,
63-
Name:"exists",
64-
OwnerName:"me",
61+
httpapi.Write(r.Context(),w,http.StatusOK,struct {
62+
Tasks []codersdk.Task`json:"tasks"`
63+
Countint`json:"count"`
64+
}{
65+
Tasks: []codersdk.Task{{
66+
ID:taskID,
67+
Name:"exists",
68+
OwnerName:"me",
69+
}},
70+
Count:1,
6571
})
6672
caser.Method==http.MethodDelete&&r.URL.Path=="/api/experimental/tasks/me/"+id1:
6773
c.deleteCalls.Add(1)
@@ -104,12 +110,18 @@ func TestExpTaskDelete(t *testing.T) {
104110
firstID:=uuid.MustParse(id3)
105111
returnfunc(w http.ResponseWriter,r*http.Request) {
106112
switch {
107-
caser.Method==http.MethodGet&&r.URL.Path=="/api/v2/users/me/workspace/first":
113+
caser.Method==http.MethodGet&&r.URL.Path=="/api/experimental/tasks"&&r.URL.Query().Get("q")=="owner:\"me\"":
108114
c.nameResolves.Add(1)
109-
httpapi.Write(r.Context(),w,http.StatusOK, codersdk.Workspace{
110-
ID:firstID,
111-
Name:"first",
112-
OwnerName:"me",
115+
httpapi.Write(r.Context(),w,http.StatusOK,struct {
116+
Tasks []codersdk.Task`json:"tasks"`
117+
Countint`json:"count"`
118+
}{
119+
Tasks: []codersdk.Task{{
120+
ID:firstID,
121+
Name:"first",
122+
OwnerName:"me",
123+
}},
124+
Count:1,
113125
})
114126
caser.Method==http.MethodGet&&r.URL.Path=="/api/experimental/tasks/me/"+id4:
115127
httpapi.Write(r.Context(),w,http.StatusOK, codersdk.Task{
@@ -139,8 +151,14 @@ func TestExpTaskDelete(t *testing.T) {
139151
buildHandler:func(_*testCounters) http.HandlerFunc {
140152
returnfunc(w http.ResponseWriter,r*http.Request) {
141153
switch {
142-
caser.Method==http.MethodGet&&r.URL.Path=="/api/v2/users/me/workspace/doesnotexist":
143-
httpapi.ResourceNotFound(w)
154+
caser.Method==http.MethodGet&&r.URL.Path=="/api/experimental/tasks"&&r.URL.Query().Get("q")=="owner:\"me\"":
155+
httpapi.Write(r.Context(),w,http.StatusOK,struct {
156+
Tasks []codersdk.Task`json:"tasks"`
157+
Countint`json:"count"`
158+
}{
159+
Tasks: []codersdk.Task{},
160+
Count:0,
161+
})
144162
default:
145163
httpapi.InternalServerError(w,xerrors.New("unwanted path: "+r.Method+" "+r.URL.Path))
146164
}
@@ -156,12 +174,18 @@ func TestExpTaskDelete(t *testing.T) {
156174
taskID:=uuid.MustParse(id5)
157175
returnfunc(w http.ResponseWriter,r*http.Request) {
158176
switch {
159-
caser.Method==http.MethodGet&&r.URL.Path=="/api/v2/users/me/workspace/bad":
177+
caser.Method==http.MethodGet&&r.URL.Path=="/api/experimental/tasks"&&r.URL.Query().Get("q")=="owner:\"me\"":
160178
c.nameResolves.Add(1)
161-
httpapi.Write(r.Context(),w,http.StatusOK, codersdk.Workspace{
162-
ID:taskID,
163-
Name:"bad",
164-
OwnerName:"me",
179+
httpapi.Write(r.Context(),w,http.StatusOK,struct {
180+
Tasks []codersdk.Task`json:"tasks"`
181+
Countint`json:"count"`
182+
}{
183+
Tasks: []codersdk.Task{{
184+
ID:taskID,
185+
Name:"bad",
186+
OwnerName:"me",
187+
}},
188+
Count:1,
165189
})
166190
caser.Method==http.MethodDelete&&r.URL.Path=="/api/experimental/tasks/me/"+id5:
167191
httpapi.InternalServerError(w,xerrors.New("boom"))

‎cli/exp_task_list.go‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"golang.org/x/xerrors"
99

1010
"github.com/coder/coder/v2/cli/cliui"
11+
"github.com/coder/coder/v2/coderd/util/slice"
1112
"github.com/coder/coder/v2/codersdk"
1213
"github.com/coder/serpent"
1314
)
@@ -98,10 +99,10 @@ func (r *RootCmd) taskList() *serpent.Command {
9899
Options: serpent.OptionSet{
99100
{
100101
Name:"status",
101-
Description:"Filter by task status (e.g. running, failed, etc).",
102+
Description:"Filter by task status.",
102103
Flag:"status",
103104
Default:"",
104-
Value:serpent.StringOf(&statusFilter),
105+
Value:serpent.EnumOf(&statusFilter,slice.ToStrings(codersdk.AllTaskStatuses())...),
105106
},
106107
{
107108
Name:"all",
@@ -142,8 +143,8 @@ func (r *RootCmd) taskList() *serpent.Command {
142143
}
143144

144145
tasks,err:=exp.Tasks(ctx,&codersdk.TasksFilter{
145-
Owner:targetUser,
146-
WorkspaceStatus:statusFilter,
146+
Owner:targetUser,
147+
Status:codersdk.TaskStatus(statusFilter),
147148
})
148149
iferr!=nil {
149150
returnxerrors.Errorf("list tasks: %w",err)

‎cli/exp_task_list_test.go‎

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ import (
2222
"github.com/coder/coder/v2/coderd/database/dbauthz"
2323
"github.com/coder/coder/v2/coderd/database/dbfake"
2424
"github.com/coder/coder/v2/coderd/database/dbgen"
25+
"github.com/coder/coder/v2/coderd/database/dbtime"
2526
"github.com/coder/coder/v2/coderd/util/slice"
2627
"github.com/coder/coder/v2/codersdk"
2728
"github.com/coder/coder/v2/pty/ptytest"
2829
"github.com/coder/coder/v2/testutil"
2930
)
3031

3132
// makeAITask creates an AI-task workspace.
32-
funcmakeAITask(t*testing.T,db database.Store,orgID,adminID,ownerID uuid.UUID,transition database.WorkspaceTransition,promptstring)(workspacedatabase.WorkspaceTable) {
33+
funcmakeAITask(t*testing.T,db database.Store,orgID,adminID,ownerID uuid.UUID,transition database.WorkspaceTransition,promptstring) database.Task {
3334
t.Helper()
3435

3536
tv:=dbfake.TemplateVersion(t,db).
@@ -91,14 +92,32 @@ func makeAITask(t *testing.T, db database.Store, orgID, adminID, ownerID uuid.UU
9192
)
9293
require.NoError(t,err)
9394

94-
returnbuild.Workspace
95+
// Create a task record in the tasks table for the new data model.
96+
task:=dbgen.Task(t,db, database.TaskTable{
97+
OrganizationID:orgID,
98+
OwnerID:ownerID,
99+
Name:build.Workspace.Name,
100+
WorkspaceID: uuid.NullUUID{UUID:build.Workspace.ID,Valid:true},
101+
TemplateVersionID:tv.TemplateVersion.ID,
102+
TemplateParameters: []byte("{}"),
103+
Prompt:prompt,
104+
CreatedAt:dbtime.Now(),
105+
})
106+
107+
// Link the task to the workspace app.
108+
dbgen.TaskWorkspaceApp(t,db, database.TaskWorkspaceApp{
109+
TaskID:task.ID,
110+
WorkspaceBuildNumber:build.Build.BuildNumber,
111+
WorkspaceAgentID: uuid.NullUUID{UUID:agentID,Valid:true},
112+
WorkspaceAppID: uuid.NullUUID{UUID:app.ID,Valid:true},
113+
})
114+
115+
returntask
95116
}
96117

97118
funcTestExpTaskList(t*testing.T) {
98119
t.Parallel()
99120

100-
t.Skip("TODO(mafredri): Remove, fixed down-stack!")
101-
102121
t.Run("NoTasks_Table",func(t*testing.T) {
103122
t.Parallel()
104123

@@ -130,7 +149,7 @@ func TestExpTaskList(t *testing.T) {
130149
memberClient,memberUser:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
131150

132151
wantPrompt:="build me a web app"
133-
ws:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,wantPrompt)
152+
task:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,wantPrompt)
134153

135154
inv,root:=clitest.New(t,"exp","task","list","--column","id,name,status,initial prompt")
136155
clitest.SetupConfig(t,memberClient,root)
@@ -142,7 +161,7 @@ func TestExpTaskList(t *testing.T) {
142161
require.NoError(t,err)
143162

144163
// Validate the table includes the task and status.
145-
pty.ExpectMatch(ws.Name)
164+
pty.ExpectMatch(task.Name)
146165
pty.ExpectMatch("running")
147166
pty.ExpectMatch(wantPrompt)
148167
})
@@ -157,11 +176,11 @@ func TestExpTaskList(t *testing.T) {
157176
memberClient,memberUser:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
158177

159178
// Create two AI tasks: one running, one stopped.
160-
running:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,"keep me running")
161-
stopped:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStop,"stop me please")
179+
runningTask:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,"keep me running")
180+
stoppedTask:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStop,"stop me please")
162181

163182
// Use JSON output to reliably validate filtering.
164-
inv,root:=clitest.New(t,"exp","task","list","--status=stopped","--output=json")
183+
inv,root:=clitest.New(t,"exp","task","list","--status=paused","--output=json")
165184
clitest.SetupConfig(t,memberClient,root)
166185

167186
ctx:=testutil.Context(t,testutil.WaitShort)
@@ -177,8 +196,8 @@ func TestExpTaskList(t *testing.T) {
177196

178197
// Only the stopped task is returned.
179198
require.Len(t,tasks,1,"expected one task after filtering")
180-
require.Equal(t,stopped.ID,tasks[0].ID)
181-
require.NotEqual(t,running.ID,tasks[0].ID)
199+
require.Equal(t,stoppedTask.ID,tasks[0].ID)
200+
require.NotEqual(t,runningTask.ID,tasks[0].ID)
182201
})
183202

184203
t.Run("UserFlag_Me_Table",func(t*testing.T) {
@@ -190,7 +209,7 @@ func TestExpTaskList(t *testing.T) {
190209
_,memberUser:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
191210

192211
_=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,"other-task")
193-
ws:=makeAITask(t,db,owner.OrganizationID,owner.UserID,owner.UserID,database.WorkspaceTransitionStart,"me-task")
212+
task:=makeAITask(t,db,owner.OrganizationID,owner.UserID,owner.UserID,database.WorkspaceTransitionStart,"me-task")
194213

195214
inv,root:=clitest.New(t,"exp","task","list","--user","me")
196215
//nolint:gocritic // Owner client is intended here smoke test the member task not showing up.
@@ -202,7 +221,7 @@ func TestExpTaskList(t *testing.T) {
202221
err:=inv.WithContext(ctx).Run()
203222
require.NoError(t,err)
204223

205-
pty.ExpectMatch(ws.Name)
224+
pty.ExpectMatch(task.Name)
206225
})
207226

208227
t.Run("Quiet",func(t*testing.T) {

‎cli/exp_task_logs.go‎

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cli
33
import (
44
"fmt"
55

6-
"github.com/google/uuid"
76
"golang.org/x/xerrors"
87

98
"github.com/coder/coder/v2/cli/cliui"
@@ -41,24 +40,17 @@ func (r *RootCmd) taskLogs() *serpent.Command {
4140
}
4241

4342
var (
44-
ctx=inv.Context()
45-
exp=codersdk.NewExperimentalClient(client)
46-
task=inv.Args[0]
47-
taskID uuid.UUID
43+
ctx=inv.Context()
44+
exp=codersdk.NewExperimentalClient(client)
45+
identifier=inv.Args[0]
4846
)
4947

50-
ifid,err:=uuid.Parse(task);err==nil {
51-
taskID=id
52-
}else {
53-
ws,err:=namedWorkspace(ctx,client,task)
54-
iferr!=nil {
55-
returnxerrors.Errorf("resolve task %q: %w",task,err)
56-
}
57-
58-
taskID=ws.ID
48+
task,err:=exp.TaskByIdentifier(ctx,identifier)
49+
iferr!=nil {
50+
returnxerrors.Errorf("resolve task %q: %w",identifier,err)
5951
}
6052

61-
logs,err:=exp.TaskLogs(ctx,codersdk.Me,taskID)
53+
logs,err:=exp.TaskLogs(ctx,codersdk.Me,task.ID)
6254
iferr!=nil {
6355
returnxerrors.Errorf("get task logs: %w",err)
6456
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp