mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Move workspaces under organizations (#1109)
This removes split ownership for workspaces. They are now a resource of organizations and have a designated owner, which is a user. This enables simple administration for commands like: - `coder stop ben/dev` - `coder build logs colin/arch` or if we decide to allow administrators to access workspaces, they could even SSH using this syntax: `coder ssh colin/dev`.
This commit is contained in:
+3
-4
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/provisioner/echo"
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
)
|
||||
@@ -44,7 +43,7 @@ func TestWorkspaceAgent(t *testing.T) {
|
||||
})
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
cmd, _ := clitest.New(t, "agent", "--auth", "azure-instance-identity", "--url", client.URL.String())
|
||||
@@ -98,7 +97,7 @@ func TestWorkspaceAgent(t *testing.T) {
|
||||
})
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
cmd, _ := clitest.New(t, "agent", "--auth", "aws-instance-identity", "--url", client.URL.String())
|
||||
@@ -152,7 +151,7 @@ func TestWorkspaceAgent(t *testing.T) {
|
||||
})
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
cmd, _ := clitest.New(t, "agent", "--auth", "google-instance-identity", "--url", client.URL.String())
|
||||
|
||||
+5
-1
@@ -42,6 +42,10 @@ func configSSH() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasPrefix(sshConfigFile, "~/") {
|
||||
dirname, _ := os.UserHomeDir()
|
||||
sshConfigFile = filepath.Join(dirname, sshConfigFile[2:])
|
||||
@@ -55,7 +59,7 @@ func configSSH() *cobra.Command {
|
||||
sshConfigContent = sshConfigContent[:startIndex-1] + sshConfigContent[endIndex+len(sshEndToken):]
|
||||
}
|
||||
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
workspaces, err := client.WorkspacesByOwner(cmd.Context(), organization.ID, codersdk.Me)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestConfigSSH(t *testing.T) {
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
agentClient := codersdk.New(client.URL)
|
||||
agentClient.SessionToken = authToken
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ func TestGitSSH(t *testing.T) {
|
||||
})
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
// start workspace agent
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ func parseScopeAndID(ctx context.Context, client *codersdk.Client, organization
|
||||
}
|
||||
scopeID = user.ID
|
||||
case codersdk.ParameterWorkspace:
|
||||
workspace, err := client.WorkspaceByName(ctx, codersdk.Me, name)
|
||||
workspace, err := client.WorkspaceByOwnerAndName(ctx, organization.ID, codersdk.Me, name)
|
||||
if err != nil {
|
||||
return scope, uuid.Nil, err
|
||||
}
|
||||
|
||||
+5
-1
@@ -327,7 +327,11 @@ func server() *cobra.Command {
|
||||
_, _ = fmt.Fprintln(cmd.OutOrStdout(), "\n\n"+cliui.Styles.Bold.Render("Interrupt caught. Gracefully exiting..."))
|
||||
|
||||
if dev {
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
organizations, err := client.OrganizationsByUser(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get organizations: %w", err)
|
||||
}
|
||||
workspaces, err := client.WorkspacesByOwner(cmd.Context(), organizations[0].ID, codersdk.Me)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get workspaces: %w", err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ func TestServer(t *testing.T) {
|
||||
version := coderdtest.CreateTemplateVersion(t, client, orgs[0].ID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, orgs[0].ID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, orgs[0].ID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
+5
-1
@@ -33,9 +33,13 @@ func ssh() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
workspaceParts := strings.Split(args[0], ".")
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceParts[0])
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, workspaceParts[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ func TestSSH(t *testing.T) {
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
cmd, root := clitest.New(t, "ssh", workspace.Name)
|
||||
clitest.SetupConfig(t, client, root)
|
||||
doneChan := make(chan struct{})
|
||||
@@ -105,7 +105,7 @@ func TestSSH(t *testing.T) {
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
go func() {
|
||||
// Run this async so the SSH command has to wait for
|
||||
// the build and agent to connect!
|
||||
|
||||
@@ -46,6 +46,10 @@ func workspaceAutostartEnable() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec := fmt.Sprintf("CRON_TZ=%s %s %s * * %s", autostartTimezone, autostartMinute, autostartHour, autostartDayOfWeek)
|
||||
validSchedule, err := schedule.Weekly(spec)
|
||||
@@ -53,7 +57,7 @@ func workspaceAutostartEnable() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -92,8 +96,12 @@ func workspaceAutostartDisable() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func TestWorkspaceAutostart(t *testing.T) {
|
||||
@@ -28,7 +27,7 @@ func TestWorkspaceAutostart(t *testing.T) {
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
|
||||
tz = "Europe/Dublin"
|
||||
cmdArgs = []string{"workspaces", "autostart", "enable", workspace.Name, "--minute", "30", "--hour", "9", "--days", "1-5", "--tz", tz}
|
||||
sched = "CRON_TZ=Europe/Dublin 30 9 * * 1-5"
|
||||
@@ -110,7 +109,7 @@ func TestWorkspaceAutostart(t *testing.T) {
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
|
||||
)
|
||||
|
||||
// check current TZ env var
|
||||
|
||||
@@ -46,6 +46,10 @@ func workspaceAutostopEnable() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec := fmt.Sprintf("CRON_TZ=%s %s %s * * %s", autostopTimezone, autostopMinute, autostopHour, autostopDayOfWeek)
|
||||
validSchedule, err := schedule.Weekly(spec)
|
||||
@@ -53,7 +57,7 @@ func workspaceAutostopEnable() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -92,8 +96,12 @@ func workspaceAutostopDisable() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func TestWorkspaceAutostop(t *testing.T) {
|
||||
@@ -28,7 +27,7 @@ func TestWorkspaceAutostop(t *testing.T) {
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
|
||||
cmdArgs = []string{"workspaces", "autostop", "enable", workspace.Name, "--minute", "30", "--hour", "17", "--days", "1-5", "--tz", "Europe/Dublin"}
|
||||
sched = "CRON_TZ=Europe/Dublin 30 17 * * 1-5"
|
||||
stdoutBuf = &bytes.Buffer{}
|
||||
@@ -109,7 +108,7 @@ func TestWorkspaceAutostop(t *testing.T) {
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
|
||||
)
|
||||
|
||||
// check current TZ env var
|
||||
|
||||
@@ -41,7 +41,7 @@ func workspaceCreate() *cobra.Command {
|
||||
workspaceName, err = cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Specify a name for your workspace:",
|
||||
Validate: func(workspaceName string) error {
|
||||
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
|
||||
_, err = client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, workspaceName)
|
||||
if err == nil {
|
||||
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func workspaceCreate() *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
|
||||
_, err = client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, workspaceName)
|
||||
if err == nil {
|
||||
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func workspaceCreate() *cobra.Command {
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
workspace, err := client.CreateWorkspace(cmd.Context(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
workspace, err := client.CreateWorkspace(cmd.Context(), organization.ID, codersdk.CreateWorkspaceRequest{
|
||||
TemplateID: template.ID,
|
||||
Name: workspaceName,
|
||||
ParameterValues: parameters,
|
||||
|
||||
@@ -21,7 +21,11 @@ func workspaceDelete() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ func workspaceList() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspaces, err := client.WorkspacesByOwner(cmd.Context(), organization.ID, codersdk.Me)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+5
-1
@@ -32,7 +32,11 @@ func validArgsWorkspaceName(cmd *cobra.Command, _ []string, toComplete string) (
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
workspaces, err := client.WorkspacesByOwner(cmd.Context(), organization.ID, codersdk.Me)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
@@ -17,7 +17,11 @@ func workspaceShow() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get workspace: %w", err)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ func workspaceStart() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ func workspaceStop() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,7 +17,11 @@ func workspaceUpdate() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user