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

Commit0f1e8c0

Browse files
author
Katie Horne
committed
Merge branch 'main' into cli-ui-copyedits
2 parentsf5e73a2 +b225953 commit0f1e8c0

File tree

11 files changed

+557
-147
lines changed

11 files changed

+557
-147
lines changed

‎cli/bump.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,26 @@ import (
88
"github.com/spf13/cobra"
99
"golang.org/x/xerrors"
1010

11+
"github.com/coder/coder/coderd/util/tz"
1112
"github.com/coder/coder/codersdk"
1213
)
1314

1415
const (
15-
bumpDescriptionLong=`To extend the autostop deadline for a workspace.`
16+
bumpDescriptionShort=`Shut your workspace down after a given duration has passed.`
17+
bumpDescriptionLong=`Modify the time at which your workspace will shut down automatically.
18+
* Provide a duration from now (for example, 1h30m).
19+
* The minimum duration is 30 minutes.
20+
* If the workspace template restricts the maximum runtime of a workspace, this will be enforced here.
21+
* If the workspace does not already have a shutdown scheduled, this does nothing.
22+
`
1623
)
1724

1825
funcbump()*cobra.Command {
1926
bumpCmd:=&cobra.Command{
2027
Args:cobra.RangeArgs(1,2),
2128
Annotations:workspaceCommand,
22-
Use:"bump <workspace-name> <duration>",
23-
Short:"Extend the autostop deadline for a workspace.",
29+
Use:"bump <workspace-name> <duration from now>",
30+
Short:bumpDescriptionShort,
2431
Long:bumpDescriptionLong,
2532
Example:"coder bump my-workspace 90m",
2633
RunE:func(cmd*cobra.Command,args []string)error {
@@ -39,17 +46,20 @@ func bump() *cobra.Command {
3946
returnxerrors.Errorf("get workspace: %w",err)
4047
}
4148

42-
newDeadline:=time.Now().Add(bumpDuration)
49+
loc,err:=tz.TimezoneIANA()
50+
iferr!=nil {
51+
loc=time.UTC// best effort
52+
}
4353

44-
ifnewDeadline.Before(workspace.LatestBuild.Deadline) {
54+
ifbumpDuration<29*time.Minute {
4555
_,_=fmt.Fprintf(
4656
cmd.OutOrStdout(),
47-
"The proposed deadline is %s before the current deadline.\n",
48-
workspace.LatestBuild.Deadline.Sub(newDeadline).Round(time.Minute),
57+
"Please specify a duration of at least 30 minutes.\n",
4958
)
5059
returnnil
5160
}
5261

62+
newDeadline:=time.Now().In(loc).Add(bumpDuration)
5363
iferr:=client.PutExtendWorkspace(cmd.Context(),workspace.ID, codersdk.PutExtendWorkspaceRequest{
5464
Deadline:newDeadline,
5565
});err!=nil {
@@ -62,7 +72,6 @@ func bump() *cobra.Command {
6272
newDeadline.Format(timeFormat),
6373
newDeadline.Format(dateFormat),
6474
)
65-
6675
returnnil
6776
},
6877
}

‎cli/bump_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ func TestBump(t *testing.T) {
124124
workspace,err=client.Workspace(ctx,workspace.ID)
125125
require.NoError(t,err)
126126

127-
//TODO(cian): need to stop and start the workspace as we do not update the deadline yet
128-
// see: https://github.com/coder/coder/issues/1783
127+
//NOTE(cian): need to stop and start the workspace as we do not update the deadline
128+
// see: https://github.com/coder/coder/issues/2224
129129
coderdtest.MustTransitionWorkspace(t,client,workspace.ID,database.WorkspaceTransitionStart,database.WorkspaceTransitionStop)
130130
coderdtest.MustTransitionWorkspace(t,client,workspace.ID,database.WorkspaceTransitionStop,database.WorkspaceTransitionStart)
131131

‎coderd/devtunnel/tunnel_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ import (
2222

2323
funcTestTunnel(t*testing.T) {
2424
t.Parallel()
25-
iftesting.Short() {
26-
t.Skip()
27-
return
28-
}
25+
26+
// It's not super useful for us to test this constantly, it'll only cause
27+
// flakes is the tunnel becomes unavailable for some reason.
28+
t.Skip()
29+
// if testing.Short() {
30+
// t.Skip()
31+
// return
32+
// }
2933

3034
ctx,cancelTun:=context.WithCancel(context.Background())
3135
defercancelTun()

‎coderd/workspaces.go

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -575,21 +575,47 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
575575
resp:= httpapi.Response{}
576576

577577
err:=api.Database.InTx(func(s database.Store)error {
578+
template,err:=s.GetTemplateByID(r.Context(),workspace.TemplateID)
579+
iferr!=nil {
580+
code=http.StatusInternalServerError
581+
resp.Message="Error fetching workspace template!"
582+
returnxerrors.Errorf("get workspace template: %w",err)
583+
}
584+
578585
build,err:=s.GetLatestWorkspaceBuildByWorkspaceID(r.Context(),workspace.ID)
579586
iferr!=nil {
580587
code=http.StatusInternalServerError
581-
resp.Message="Workspace not found."
588+
resp.Message="Error fetching workspace build."
582589
returnxerrors.Errorf("get latest workspace build: %w",err)
583590
}
584591

592+
job,err:=s.GetProvisionerJobByID(r.Context(),build.JobID)
593+
iferr!=nil {
594+
code=http.StatusInternalServerError
595+
resp.Message="Error fetching workspace provisioner job."
596+
returnxerrors.Errorf("get provisioner job: %w",err)
597+
}
598+
585599
ifbuild.Transition!=database.WorkspaceTransitionStart {
586600
code=http.StatusConflict
587601
resp.Message="Workspace must be started, current status: "+string(build.Transition)
588602
returnxerrors.Errorf("workspace must be started, current status: %s",build.Transition)
589603
}
590604

605+
if!job.CompletedAt.Valid {
606+
code=http.StatusConflict
607+
resp.Message="Workspace is still building!"
608+
returnxerrors.Errorf("workspace is still building")
609+
}
610+
611+
ifbuild.Deadline.IsZero() {
612+
code=http.StatusConflict
613+
resp.Message="Workspace shutdown is manual."
614+
returnxerrors.Errorf("workspace shutdown is manual")
615+
}
616+
591617
newDeadline:=req.Deadline.UTC()
592-
iferr:=validWorkspaceDeadline(build.Deadline,newDeadline);err!=nil {
618+
iferr:=validWorkspaceDeadline(job.CompletedAt.Time,newDeadline,time.Duration(template.MaxTtl));err!=nil {
593619
code=http.StatusBadRequest
594620
resp.Message="Bad extend workspace request."
595621
resp.Validations=append(resp.Validations, httpapi.Error{Field:"deadline",Detail:err.Error()})
@@ -878,23 +904,20 @@ func validWorkspaceTTLMillis(millis *int64, max time.Duration) (sql.NullInt64, e
878904
},nil
879905
}
880906

881-
funcvalidWorkspaceDeadline(old,new time.Time)error {
882-
ifold.IsZero() {
883-
returnxerrors.New("nothing to do: no existing deadline set")
884-
}
885-
886-
now:=time.Now()
887-
ifnew.Before(now) {
888-
returnxerrors.New("new deadline must be in the future")
907+
funcvalidWorkspaceDeadline(startedAt,newDeadline time.Time,max time.Duration)error {
908+
soon:=time.Now().Add(29*time.Minute)
909+
ifnewDeadline.Before(soon) {
910+
returnxerrors.New("new deadline must be at least 30 minutes in the future")
889911
}
890912

891-
delta:=new.Sub(old)
892-
ifdelta<time.Minute {
893-
returnxerrors.New("minimum extension is one minute")
913+
// No idea how this could happen.
914+
ifnewDeadline.Before(startedAt) {
915+
returnxerrors.Errorf("new deadline must be before workspace start time")
894916
}
895917

896-
ifdelta>24*time.Hour {
897-
returnxerrors.New("maximum extension is 24 hours")
918+
delta:=newDeadline.Sub(startedAt)
919+
ifdelta>max {
920+
returnxerrors.New("new deadline is greater than template allows")
898921
}
899922

900923
returnnil

‎coderd/workspaces_test.go

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -974,22 +974,23 @@ func TestWorkspaceUpdateTTL(t *testing.T) {
974974
funcTestWorkspaceExtend(t*testing.T) {
975975
t.Parallel()
976976
var (
977+
ttl=8*time.Hour
978+
newDeadline=time.Now().Add(ttl+time.Hour).UTC()
977979
ctx=context.Background()
978980
client=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerD:true})
979981
user=coderdtest.CreateFirstUser(t,client)
980982
version=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
981983
_=coderdtest.AwaitTemplateVersionJob(t,client,version.ID)
982-
project=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
983-
workspace=coderdtest.CreateWorkspace(t,client,user.OrganizationID,project.ID)
984-
extend=90*time.Minute
985-
_=coderdtest.AwaitWorkspaceBuildJob(t,client,workspace.LatestBuild.ID)
986-
oldDeadline=time.Now().Add(time.Duration(*workspace.TTLMillis)*time.Millisecond).UTC()
987-
newDeadline=time.Now().Add(time.Duration(*workspace.TTLMillis)*time.Millisecond+extend).UTC()
984+
template=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
985+
workspace=coderdtest.CreateWorkspace(t,client,user.OrganizationID,template.ID,func(cwr*codersdk.CreateWorkspaceRequest) {
986+
cwr.TTLMillis=ptr.Ref(ttl.Milliseconds())
987+
})
988+
_=coderdtest.AwaitWorkspaceBuildJob(t,client,workspace.LatestBuild.ID)
988989
)
989990

990991
workspace,err:=client.Workspace(ctx,workspace.ID)
991992
require.NoError(t,err,"fetch provisioned workspace")
992-
require.InDelta(t,oldDeadline.Unix(),workspace.LatestBuild.Deadline.Unix(),60)
993+
oldDeadline:=workspace.LatestBuild.Deadline
993994

994995
// Updating the deadline should succeed
995996
req:= codersdk.PutExtendWorkspaceRequest{
@@ -1001,30 +1002,45 @@ func TestWorkspaceExtend(t *testing.T) {
10011002
// Ensure deadline set correctly
10021003
updated,err:=client.Workspace(ctx,workspace.ID)
10031004
require.NoError(t,err,"failed to fetch updated workspace")
1004-
require.InDelta(t,newDeadline.Unix(),updated.LatestBuild.Deadline.Unix(),60)
1005+
require.WithinDuration(t,newDeadline,updated.LatestBuild.Deadline,time.Minute)
10051006

10061007
// Zero time should fail
10071008
err=client.PutExtendWorkspace(ctx,workspace.ID, codersdk.PutExtendWorkspaceRequest{
10081009
Deadline: time.Time{},
10091010
})
10101011
require.ErrorContains(t,err,"deadline: Validation failed for tag\"required\" with value:\"0001-01-01 00:00:00 +0000 UTC\"","setting an empty deadline on a workspace should fail")
10111012

1012-
// Updating with an earlier time should also fail
1013+
// Updating with a deadline 29 minutes in the future should fail
1014+
deadlineTooSoon:=time.Now().Add(29*time.Minute)
1015+
err=client.PutExtendWorkspace(ctx,workspace.ID, codersdk.PutExtendWorkspaceRequest{
1016+
Deadline:deadlineTooSoon,
1017+
})
1018+
require.ErrorContains(t,err,"new deadline must be at least 30 minutes in the future","setting a deadline less than 30 minutes in the future should fail")
1019+
1020+
// And with a deadline greater than the template max_ttl should also fail
1021+
deadlineExceedsMaxTTL:=time.Now().Add(time.Duration(template.MaxTTLMillis)*time.Millisecond).Add(time.Minute)
1022+
err=client.PutExtendWorkspace(ctx,workspace.ID, codersdk.PutExtendWorkspaceRequest{
1023+
Deadline:deadlineExceedsMaxTTL,
1024+
})
1025+
require.ErrorContains(t,err,"new deadline is greater than template allows","setting a deadline greater than that allowed by the template should fail")
1026+
1027+
// Updating with a deadline 30 minutes in the future should succeed
1028+
deadlineJustSoonEnough:=time.Now().Add(30*time.Minute)
10131029
err=client.PutExtendWorkspace(ctx,workspace.ID, codersdk.PutExtendWorkspaceRequest{
1014-
Deadline:oldDeadline,
1030+
Deadline:deadlineJustSoonEnough,
10151031
})
1016-
require.ErrorContains(t,err,"deadline: minimum extension is one minute","setting an earlier deadline shouldfail")
1032+
require.NoError(t,err,"setting a deadline at least 30 minutes in the future shouldsucceed")
10171033

1018-
// Updating with atime far inthefutureshouldalso fail
1034+
// Updating with adeadline an hour beforetheprevious deadlineshouldsucceed
10191035
err=client.PutExtendWorkspace(ctx,workspace.ID, codersdk.PutExtendWorkspaceRequest{
1020-
Deadline:oldDeadline.AddDate(1,0,0),
1036+
Deadline:oldDeadline.Add(-time.Hour),
10211037
})
1022-
require.ErrorContains(t,err,"deadline: maximum extension is 24 hours","setting an earlier deadline should fail")
1038+
require.NoError(t,err,"setting an earlier deadline should not fail")
10231039

10241040
// Ensure deadline still set correctly
10251041
updated,err=client.Workspace(ctx,workspace.ID)
10261042
require.NoError(t,err,"failed to fetch updated workspace")
1027-
require.InDelta(t,newDeadline.Unix(),updated.LatestBuild.Deadline.Unix(),60)
1043+
require.WithinDuration(t,oldDeadline.Add(-time.Hour),updated.LatestBuild.Deadline,time.Minute)
10281044
}
10291045

10301046
funcTestWorkspaceWatcher(t*testing.T) {

‎site/src/components/GlobalSnackbar/GlobalSnackbar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const GlobalSnackbar: React.FC = () => {
7272

7373
return(
7474
<EnterpriseSnackbar
75+
key={notification.msg}
7576
open={open}
7677
variant={variantFromMsgType(notification.msgType)}
7778
message={

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp