Skip to content

Commit b267497

Browse files
authored
fix: parse username/workspace correctly on coder state pull --build (#10973)
fixes #10884
1 parent 46d95cb commit b267497

File tree

2 files changed

+49
-37
lines changed

2 files changed

+49
-37
lines changed

cli/state.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ func (r *RootCmd) statePull() *clibase.Cmd {
4646
}
4747
build = workspace.LatestBuild
4848
} else {
49-
build, err = client.WorkspaceBuildByUsernameAndWorkspaceNameAndBuildNumber(inv.Context(), codersdk.Me, inv.Args[0], strconv.FormatInt(buildNumber, 10))
49+
owner, workspace, err := splitNamedWorkspace(inv.Args[0])
50+
if err != nil {
51+
return err
52+
}
53+
build, err = client.WorkspaceBuildByUsernameAndWorkspaceNameAndBuildNumber(inv.Context(), owner, workspace, strconv.FormatInt(buildNumber, 10))
5054
if err != nil {
5155
return err
5256
}

cli/state_test.go

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,40 @@ package cli_test
22

33
import (
44
"bytes"
5+
"fmt"
56
"os"
67
"path/filepath"
78
"strconv"
89
"strings"
910
"testing"
1011

12+
"github.com/coder/coder/v2/coderd/database"
13+
"github.com/coder/coder/v2/coderd/database/dbfake"
14+
1115
"github.com/stretchr/testify/require"
1216

1317
"github.com/coder/coder/v2/cli/clitest"
1418
"github.com/coder/coder/v2/coderd/coderdtest"
1519
"github.com/coder/coder/v2/coderd/rbac"
1620
"github.com/coder/coder/v2/provisioner/echo"
17-
"github.com/coder/coder/v2/provisionersdk/proto"
1821
)
1922

2023
func TestStatePull(t *testing.T) {
2124
t.Parallel()
2225
t.Run("File", func(t *testing.T) {
2326
t.Parallel()
24-
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
27+
client, store := coderdtest.NewWithDatabase(t, nil)
2528
owner := coderdtest.CreateFirstUser(t, client)
26-
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
29+
templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
2730
wantState := []byte("some state")
28-
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{
29-
Parse: echo.ParseComplete,
30-
ProvisionApply: []*proto.Response{{
31-
Type: &proto.Response_Apply{
32-
Apply: &proto.ApplyComplete{
33-
State: wantState,
34-
},
35-
},
36-
}},
37-
})
38-
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
39-
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
40-
// Need to create workspace as templateAdmin to ensure we can read state.
41-
workspace := coderdtest.CreateWorkspace(t, templateAdmin, owner.OrganizationID, template.ID)
42-
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
31+
r := dbfake.WorkspaceBuild(t, store, database.Workspace{
32+
OrganizationID: owner.OrganizationID,
33+
OwnerID: taUser.ID,
34+
}).
35+
Seed(database.WorkspaceBuild{ProvisionerState: wantState}).
36+
Do()
4337
statefilePath := filepath.Join(t.TempDir(), "state")
44-
inv, root := clitest.New(t, "state", "pull", workspace.Name, statefilePath)
38+
inv, root := clitest.New(t, "state", "pull", r.Workspace.Name, statefilePath)
4539
clitest.SetupConfig(t, templateAdmin, root)
4640
err := inv.Run()
4741
require.NoError(t, err)
@@ -51,32 +45,46 @@ func TestStatePull(t *testing.T) {
5145
})
5246
t.Run("Stdout", func(t *testing.T) {
5347
t.Parallel()
54-
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
48+
client, store := coderdtest.NewWithDatabase(t, nil)
5549
owner := coderdtest.CreateFirstUser(t, client)
56-
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
50+
templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
5751
wantState := []byte("some state")
58-
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{
59-
Parse: echo.ParseComplete,
60-
ProvisionApply: []*proto.Response{{
61-
Type: &proto.Response_Apply{
62-
Apply: &proto.ApplyComplete{
63-
State: wantState,
64-
},
65-
},
66-
}},
67-
})
68-
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
69-
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
70-
workspace := coderdtest.CreateWorkspace(t, templateAdmin, owner.OrganizationID, template.ID)
71-
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
72-
inv, root := clitest.New(t, "state", "pull", workspace.Name)
52+
r := dbfake.WorkspaceBuild(t, store, database.Workspace{
53+
OrganizationID: owner.OrganizationID,
54+
OwnerID: taUser.ID,
55+
}).
56+
Seed(database.WorkspaceBuild{ProvisionerState: wantState}).
57+
Do()
58+
inv, root := clitest.New(t, "state", "pull", r.Workspace.Name)
7359
var gotState bytes.Buffer
7460
inv.Stdout = &gotState
7561
clitest.SetupConfig(t, templateAdmin, root)
7662
err := inv.Run()
7763
require.NoError(t, err)
7864
require.Equal(t, wantState, bytes.TrimSpace(gotState.Bytes()))
7965
})
66+
t.Run("OtherUserBuild", func(t *testing.T) {
67+
t.Parallel()
68+
client, store := coderdtest.NewWithDatabase(t, nil)
69+
owner := coderdtest.CreateFirstUser(t, client)
70+
_, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
71+
wantState := []byte("some state")
72+
r := dbfake.WorkspaceBuild(t, store, database.Workspace{
73+
OrganizationID: owner.OrganizationID,
74+
OwnerID: taUser.ID,
75+
}).
76+
Seed(database.WorkspaceBuild{ProvisionerState: wantState}).
77+
Do()
78+
inv, root := clitest.New(t, "state", "pull", taUser.Username+"/"+r.Workspace.Name,
79+
"--build", fmt.Sprintf("%d", r.Build.BuildNumber))
80+
var gotState bytes.Buffer
81+
inv.Stdout = &gotState
82+
//nolint: gocritic // this tests owner pulling another user's state
83+
clitest.SetupConfig(t, client, root)
84+
err := inv.Run()
85+
require.NoError(t, err)
86+
require.Equal(t, wantState, bytes.TrimSpace(gotState.Bytes()))
87+
})
8088
}
8189

8290
func TestStatePush(t *testing.T) {

0 commit comments

Comments
 (0)