mirror of https://github.com/coder/coder.git
chore: update v1 schema (#643)
This commit is contained in:
parent
cbb82ce017
commit
2b1a0ee126
|
@ -187,6 +187,7 @@ linters-settings:
|
|||
- t
|
||||
- id
|
||||
- wg
|
||||
- Me
|
||||
# Optional list of variable declarations that should be ignored completely. (defaults to empty list)
|
||||
# Entries must be in the form of "<variable name> <type>" or "<variable name> *<type>" for
|
||||
# variables, or "const <name>" for constants.
|
||||
|
|
1
Makefile
1
Makefile
|
@ -12,6 +12,7 @@ build: site/out bin
|
|||
# Runs migrations to output a dump of the database.
|
||||
coderd/database/dump.sql: $(wildcard coderd/database/migrations/*.sql)
|
||||
go run coderd/database/dump/main.go
|
||||
.PHONY: coderd/database/dump.sql
|
||||
|
||||
# Generates Go code for querying the database.
|
||||
coderd/database/generate: fmt/sql coderd/database/dump.sql coderd/database/query.sql
|
||||
|
|
|
@ -52,7 +52,7 @@ func configSSH() *cobra.Command {
|
|||
sshConfigContent = sshConfigContent[:startIndex-1] + sshConfigContent[endIndex+len(sshEndToken):]
|
||||
}
|
||||
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), "")
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/pty/ptytest"
|
||||
)
|
||||
|
||||
|
@ -21,7 +22,7 @@ func TestConfigSSH(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
tempFile, err := os.CreateTemp(t.TempDir(), "")
|
||||
require.NoError(t, err)
|
||||
|
|
12
cli/login.go
12
cli/login.go
|
@ -119,10 +119,10 @@ func login() *cobra.Command {
|
|||
}
|
||||
|
||||
_, err = client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
|
||||
Email: email,
|
||||
Username: username,
|
||||
Organization: username,
|
||||
Password: password,
|
||||
Email: email,
|
||||
Username: username,
|
||||
OrganizationName: username,
|
||||
Password: password,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create initial user: %w", err)
|
||||
|
@ -167,7 +167,7 @@ func login() *cobra.Command {
|
|||
Secret: true,
|
||||
Validate: func(token string) error {
|
||||
client.SessionToken = token
|
||||
_, err := client.User(cmd.Context(), "me")
|
||||
_, err := client.User(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return xerrors.New("That's not a valid token!")
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ func login() *cobra.Command {
|
|||
|
||||
// Login to get user data - verify it is OK before persisting
|
||||
client.SessionToken = sessionToken
|
||||
resp, err := client.User(cmd.Context(), "me")
|
||||
resp, err := client.User(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get user: %w", err)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package cli
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
|
@ -20,42 +21,45 @@ func parameters() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func parseScopeAndID(ctx context.Context, client *codersdk.Client, organization codersdk.Organization, rawScope string, name string) (codersdk.ParameterScope, string, error) {
|
||||
func parseScopeAndID(ctx context.Context, client *codersdk.Client, organization codersdk.Organization, rawScope string, name string) (codersdk.ParameterScope, uuid.UUID, error) {
|
||||
scope, err := parseParameterScope(rawScope)
|
||||
if err != nil {
|
||||
return scope, "", err
|
||||
return scope, uuid.Nil, err
|
||||
}
|
||||
var scopeID string
|
||||
|
||||
var scopeID uuid.UUID
|
||||
switch scope {
|
||||
case codersdk.ParameterOrganization:
|
||||
if name == "" {
|
||||
scopeID = organization.ID
|
||||
} else {
|
||||
org, err := client.OrganizationByName(ctx, "", name)
|
||||
org, err := client.OrganizationByName(ctx, codersdk.Me, name)
|
||||
if err != nil {
|
||||
return scope, "", err
|
||||
return scope, uuid.Nil, err
|
||||
}
|
||||
scopeID = org.ID
|
||||
}
|
||||
case codersdk.ParameterProject:
|
||||
project, err := client.ProjectByName(ctx, organization.ID, name)
|
||||
if err != nil {
|
||||
return scope, "", err
|
||||
return scope, uuid.Nil, err
|
||||
}
|
||||
scopeID = project.ID.String()
|
||||
scopeID = project.ID
|
||||
case codersdk.ParameterUser:
|
||||
user, err := client.User(ctx, name)
|
||||
uid, _ := uuid.Parse(name)
|
||||
user, err := client.User(ctx, uid)
|
||||
if err != nil {
|
||||
return scope, "", err
|
||||
return scope, uuid.Nil, err
|
||||
}
|
||||
scopeID = user.ID
|
||||
case codersdk.ParameterWorkspace:
|
||||
workspace, err := client.WorkspaceByName(ctx, "", name)
|
||||
workspace, err := client.WorkspaceByName(ctx, codersdk.Me, name)
|
||||
if err != nil {
|
||||
return scope, "", err
|
||||
return scope, uuid.Nil, err
|
||||
}
|
||||
scopeID = workspace.ID.String()
|
||||
scopeID = workspace.ID
|
||||
}
|
||||
|
||||
return scope, scopeID, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ func createClient(cmd *cobra.Command) (*codersdk.Client, error) {
|
|||
|
||||
// currentOrganization returns the currently active organization for the authenticated user.
|
||||
func currentOrganization(cmd *cobra.Command, client *codersdk.Client) (codersdk.Organization, error) {
|
||||
orgs, err := client.OrganizationsByUser(cmd.Context(), "me")
|
||||
orgs, err := client.OrganizationsByUser(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return codersdk.Organization{}, nil
|
||||
}
|
||||
|
|
14
cli/ssh.go
14
cli/ssh.go
|
@ -32,26 +32,32 @@ func ssh() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), "", args[0])
|
||||
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if workspace.LatestBuild.Transition != database.WorkspaceTransitionStart {
|
||||
return xerrors.New("workspace must be in start transition to ssh")
|
||||
}
|
||||
|
||||
if workspace.LatestBuild.Job.CompletedAt == nil {
|
||||
err = cliui.WorkspaceBuild(cmd.Context(), cmd.ErrOrStderr(), client, workspace.LatestBuild.ID, workspace.CreatedAt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if workspace.LatestBuild.Transition == database.WorkspaceTransitionDelete {
|
||||
return xerrors.New("workspace is deleting...")
|
||||
}
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(cmd.Context(), workspace.LatestBuild.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resourceByAddress := make(map[string]codersdk.WorkspaceResource)
|
||||
for _, resource := range resources {
|
||||
if resource.Agent == nil {
|
||||
|
@ -59,6 +65,7 @@ func ssh() *cobra.Command {
|
|||
}
|
||||
resourceByAddress[resource.Address] = resource
|
||||
}
|
||||
|
||||
var resourceAddress string
|
||||
if len(args) >= 2 {
|
||||
resourceAddress = args[1]
|
||||
|
@ -73,6 +80,7 @@ func ssh() *cobra.Command {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
resource, exists := resourceByAddress[resourceAddress]
|
||||
if !exists {
|
||||
resourceKeys := make([]string, 0)
|
||||
|
@ -100,6 +108,7 @@ func ssh() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
if stdio {
|
||||
rawSSH, err := conn.SSH()
|
||||
if err != nil {
|
||||
|
@ -135,13 +144,16 @@ func ssh() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sshSession.Stdin = cmd.InOrStdin()
|
||||
sshSession.Stdout = cmd.OutOrStdout()
|
||||
sshSession.Stderr = cmd.OutOrStdout()
|
||||
|
||||
err = sshSession.Shell()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = sshSession.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -53,7 +53,7 @@ func TestSSH(t *testing.T) {
|
|||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
go func() {
|
||||
// Run this async so the SSH command has to wait for
|
||||
// the build and agent to connect!
|
||||
|
@ -111,7 +111,7 @@ func TestSSH(t *testing.T) {
|
|||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
go func() {
|
||||
// Run this async so the SSH command has to wait for
|
||||
// the build and agent to connect!
|
||||
|
|
10
cli/start.go
10
cli/start.go
|
@ -255,7 +255,7 @@ func start() *cobra.Command {
|
|||
_, _ = fmt.Fprintln(cmd.OutOrStdout(), "\n\n"+cliui.Styles.Bold.Render("Interrupt caught. Gracefully exiting..."))
|
||||
|
||||
if dev {
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), "")
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get workspaces: %w", err)
|
||||
}
|
||||
|
@ -343,10 +343,10 @@ func start() *cobra.Command {
|
|||
|
||||
func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Root) error {
|
||||
_, err := client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
|
||||
Email: "admin@coder.com",
|
||||
Username: "developer",
|
||||
Password: "password",
|
||||
Organization: "acme-corp",
|
||||
Email: "admin@coder.com",
|
||||
Username: "developer",
|
||||
Password: "password",
|
||||
OrganizationName: "acme-corp",
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create first user: %w", err)
|
||||
|
|
|
@ -59,10 +59,10 @@ func TestStart(t *testing.T) {
|
|||
return true
|
||||
}, 15*time.Second, 25*time.Millisecond)
|
||||
_, err = client.CreateFirstUser(ctx, codersdk.CreateFirstUserRequest{
|
||||
Email: "some@one.com",
|
||||
Username: "example",
|
||||
Password: "password",
|
||||
Organization: "example",
|
||||
Email: "some@one.com",
|
||||
Username: "example",
|
||||
Password: "password",
|
||||
OrganizationName: "example",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
cancelFunc()
|
||||
|
@ -90,7 +90,7 @@ func TestStart(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
client := codersdk.New(parsed)
|
||||
client.SessionToken = token
|
||||
_, err = client.User(ctx, "")
|
||||
_, err = client.User(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("TLSBadVersion", func(t *testing.T) {
|
||||
|
@ -182,7 +182,7 @@ func TestStart(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
client := codersdk.New(parsed)
|
||||
client.SessionToken = token
|
||||
orgs, err := client.OrganizationsByUser(ctx, "")
|
||||
orgs, err := client.OrganizationsByUser(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
|
||||
|
@ -190,7 +190,7 @@ func TestStart(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, orgs[0].ID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, orgs[0].ID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -8,6 +8,7 @@ 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"
|
||||
)
|
||||
|
@ -43,7 +44,7 @@ func TestWorkspaceAgent(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
cmd, _ := clitest.New(t, "workspaces", "agent", "--auth", "aws-instance-identity", "--url", client.URL.String())
|
||||
|
@ -97,7 +98,7 @@ func TestWorkspaceAgent(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
cmd, _ := clitest.New(t, "workspaces", "agent", "--auth", "google-instance-identity", "--url", client.URL.String())
|
||||
|
|
|
@ -74,7 +74,7 @@ func workspaceCreate() *cobra.Command {
|
|||
_, _ = fmt.Fprintln(cmd.OutOrStdout(), cliui.Styles.Prompt.String()+"Creating with the "+cliui.Styles.Field.Render(project.Name)+" project...")
|
||||
|
||||
workspaceName := args[0]
|
||||
_, err = client.WorkspaceByName(cmd.Context(), "", workspaceName)
|
||||
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
|
||||
if err == nil {
|
||||
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ func workspaceCreate() *cobra.Command {
|
|||
}
|
||||
|
||||
before := time.Now()
|
||||
workspace, err := client.CreateWorkspace(cmd.Context(), "", codersdk.CreateWorkspaceRequest{
|
||||
workspace, err := client.CreateWorkspace(cmd.Context(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: workspaceName,
|
||||
ParameterValues: parameters,
|
||||
|
|
|
@ -21,7 +21,7 @@ func workspaceDelete() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), "", args[0])
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/coder/coder/cli/cliui"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func workspaceList() *cobra.Command {
|
||||
|
@ -21,7 +22,7 @@ func workspaceList() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
start := time.Now()
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), "")
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func workspaces() *cobra.Command {
|
||||
|
@ -29,7 +31,7 @@ func validArgsWorkspaceName(cmd *cobra.Command, _ []string, toComplete string) (
|
|||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), "")
|
||||
workspaces, err := client.WorkspacesByUser(cmd.Context(), codersdk.Me)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func workspaceShow() *cobra.Command {
|
||||
|
@ -14,7 +16,7 @@ func workspaceShow() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), "", args[0])
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func workspaceStart() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), "", args[0])
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func workspaceStop() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), "", args[0])
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func workspaceUpdate() *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), "", args[0])
|
||||
workspace, err := client.WorkspaceByName(cmd.Context(), codersdk.Me, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -99,10 +99,10 @@ func parse(cmd *cobra.Command, parameters []codersdk.CreateParameterRequest) err
|
|||
defer daemonClose.Close()
|
||||
|
||||
created, err := client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
|
||||
Email: "templater@coder.com",
|
||||
Username: "templater",
|
||||
Organization: "templater",
|
||||
Password: "insecure",
|
||||
Email: "templater@coder.com",
|
||||
Username: "templater",
|
||||
OrganizationName: "templater",
|
||||
Password: "insecure",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -155,10 +155,10 @@ func NewProvisionerDaemon(t *testing.T, client *codersdk.Client) io.Closer {
|
|||
// with the passed in codersdk client.
|
||||
func CreateFirstUser(t *testing.T, client *codersdk.Client) codersdk.CreateFirstUserResponse {
|
||||
req := codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Organization: "testorg",
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
OrganizationName: "testorg",
|
||||
}
|
||||
resp, err := client.CreateFirstUser(context.Background(), req)
|
||||
require.NoError(t, err)
|
||||
|
@ -173,12 +173,12 @@ func CreateFirstUser(t *testing.T, client *codersdk.Client) codersdk.CreateFirst
|
|||
}
|
||||
|
||||
// CreateAnotherUser creates and authenticates a new user.
|
||||
func CreateAnotherUser(t *testing.T, client *codersdk.Client, organization string) *codersdk.Client {
|
||||
func CreateAnotherUser(t *testing.T, client *codersdk.Client, organizationID uuid.UUID) *codersdk.Client {
|
||||
req := codersdk.CreateUserRequest{
|
||||
Email: namesgenerator.GetRandomName(1) + "@coder.com",
|
||||
Username: randomUsername(),
|
||||
Password: "testpass",
|
||||
OrganizationID: organization,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
_, err := client.CreateUser(context.Background(), req)
|
||||
require.NoError(t, err)
|
||||
|
@ -197,12 +197,12 @@ func CreateAnotherUser(t *testing.T, client *codersdk.Client, organization strin
|
|||
// CreateProjectVersion creates a project import provisioner job
|
||||
// with the responses provided. It uses the "echo" provisioner for compatibility
|
||||
// with testing.
|
||||
func CreateProjectVersion(t *testing.T, client *codersdk.Client, organization string, res *echo.Responses) codersdk.ProjectVersion {
|
||||
func CreateProjectVersion(t *testing.T, client *codersdk.Client, organizationID uuid.UUID, res *echo.Responses) codersdk.ProjectVersion {
|
||||
data, err := echo.Tar(res)
|
||||
require.NoError(t, err)
|
||||
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, data)
|
||||
require.NoError(t, err)
|
||||
projectVersion, err := client.CreateProjectVersion(context.Background(), organization, codersdk.CreateProjectVersionRequest{
|
||||
projectVersion, err := client.CreateProjectVersion(context.Background(), organizationID, codersdk.CreateProjectVersionRequest{
|
||||
StorageSource: file.Hash,
|
||||
StorageMethod: database.ProvisionerStorageMethodFile,
|
||||
Provisioner: database.ProvisionerTypeEcho,
|
||||
|
@ -213,7 +213,7 @@ func CreateProjectVersion(t *testing.T, client *codersdk.Client, organization st
|
|||
|
||||
// CreateProject creates a project with the "echo" provisioner for
|
||||
// compatibility with testing. The name assigned is randomly generated.
|
||||
func CreateProject(t *testing.T, client *codersdk.Client, organization string, version uuid.UUID) codersdk.Project {
|
||||
func CreateProject(t *testing.T, client *codersdk.Client, organization uuid.UUID, version uuid.UUID) codersdk.Project {
|
||||
project, err := client.CreateProject(context.Background(), organization, codersdk.CreateProjectRequest{
|
||||
Name: randomUsername(),
|
||||
VersionID: version,
|
||||
|
@ -268,7 +268,7 @@ func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, build uuid.UUID
|
|||
|
||||
// CreateWorkspace creates a workspace for the user and project provided.
|
||||
// A random name is generated for it.
|
||||
func CreateWorkspace(t *testing.T, client *codersdk.Client, user string, projectID uuid.UUID) codersdk.Workspace {
|
||||
func CreateWorkspace(t *testing.T, client *codersdk.Client, user uuid.UUID, projectID uuid.UUID) codersdk.Workspace {
|
||||
workspace, err := client.CreateWorkspace(context.Background(), user, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: projectID,
|
||||
Name: randomUsername(),
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"go.uber.org/goleak"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -20,7 +21,7 @@ func TestNew(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
_, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false)
|
||||
|
|
|
@ -143,7 +143,7 @@ func (q *fakeQuerier) GetUserByEmailOrUsername(_ context.Context, arg database.G
|
|||
return database.User{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetUserByID(_ context.Context, id string) (database.User, error) {
|
||||
func (q *fakeQuerier) GetUserByID(_ context.Context, id uuid.UUID) (database.User, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
|
@ -217,34 +217,33 @@ func (q *fakeQuerier) GetWorkspaceOwnerCountsByProjectIDs(_ context.Context, pro
|
|||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
counts := map[string]map[string]struct{}{}
|
||||
counts := map[uuid.UUID]map[uuid.UUID]struct{}{}
|
||||
for _, projectID := range projectIDs {
|
||||
found := false
|
||||
for _, workspace := range q.workspace {
|
||||
if workspace.ProjectID.String() != projectID.String() {
|
||||
if workspace.ProjectID != projectID {
|
||||
continue
|
||||
}
|
||||
if workspace.Deleted {
|
||||
continue
|
||||
}
|
||||
countByOwnerID, ok := counts[projectID.String()]
|
||||
countByOwnerID, ok := counts[projectID]
|
||||
if !ok {
|
||||
countByOwnerID = map[string]struct{}{}
|
||||
countByOwnerID = map[uuid.UUID]struct{}{}
|
||||
}
|
||||
countByOwnerID[workspace.OwnerID] = struct{}{}
|
||||
counts[projectID.String()] = countByOwnerID
|
||||
counts[projectID] = countByOwnerID
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if !found {
|
||||
counts[projectID.String()] = map[string]struct{}{}
|
||||
counts[projectID] = map[uuid.UUID]struct{}{}
|
||||
}
|
||||
}
|
||||
res := make([]database.GetWorkspaceOwnerCountsByProjectIDsRow, 0)
|
||||
for key, value := range counts {
|
||||
uid := uuid.MustParse(key)
|
||||
res = append(res, database.GetWorkspaceOwnerCountsByProjectIDsRow{
|
||||
ProjectID: uid,
|
||||
ProjectID: key,
|
||||
Count: int64(len(value)),
|
||||
})
|
||||
}
|
||||
|
@ -364,7 +363,7 @@ func (q *fakeQuerier) GetWorkspacesByUserID(_ context.Context, req database.GetW
|
|||
return workspaces, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizationByID(_ context.Context, id string) (database.Organization, error) {
|
||||
func (q *fakeQuerier) GetOrganizationByID(_ context.Context, id uuid.UUID) (database.Organization, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
|
@ -388,7 +387,7 @@ func (q *fakeQuerier) GetOrganizationByName(_ context.Context, name string) (dat
|
|||
return database.Organization{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizationsByUserID(_ context.Context, userID string) ([]database.Organization, error) {
|
||||
func (q *fakeQuerier) GetOrganizationsByUserID(_ context.Context, userID uuid.UUID) ([]database.Organization, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
|
@ -483,7 +482,7 @@ func (q *fakeQuerier) GetProjectVersionByProjectIDAndName(_ context.Context, arg
|
|||
defer q.mutex.RUnlock()
|
||||
|
||||
for _, projectVersion := range q.projectVersion {
|
||||
if projectVersion.ProjectID.UUID.String() != arg.ProjectID.UUID.String() {
|
||||
if projectVersion.ProjectID != arg.ProjectID {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(projectVersion.Name, arg.Name) {
|
||||
|
@ -1056,7 +1055,7 @@ func (q *fakeQuerier) InsertWorkspaceBuild(_ context.Context, arg database.Inser
|
|||
ProjectVersionID: arg.ProjectVersionID,
|
||||
BeforeID: arg.BeforeID,
|
||||
Transition: arg.Transition,
|
||||
Initiator: arg.Initiator,
|
||||
InitiatorID: arg.InitiatorID,
|
||||
JobID: arg.JobID,
|
||||
ProvisionerState: arg.ProvisionerState,
|
||||
}
|
||||
|
|
|
@ -57,12 +57,6 @@ CREATE TYPE provisioner_type AS ENUM (
|
|||
'terraform'
|
||||
);
|
||||
|
||||
CREATE TYPE userstatus AS ENUM (
|
||||
'active',
|
||||
'dormant',
|
||||
'decommissioned'
|
||||
);
|
||||
|
||||
CREATE TYPE workspace_transition AS ENUM (
|
||||
'start',
|
||||
'stop',
|
||||
|
@ -72,7 +66,7 @@ CREATE TYPE workspace_transition AS ENUM (
|
|||
CREATE TABLE api_keys (
|
||||
id text NOT NULL,
|
||||
hashed_secret bytea NOT NULL,
|
||||
user_id text NOT NULL,
|
||||
user_id uuid NOT NULL,
|
||||
application boolean NOT NULL,
|
||||
name text NOT NULL,
|
||||
last_used timestamp with time zone NOT NULL,
|
||||
|
@ -90,7 +84,7 @@ CREATE TABLE api_keys (
|
|||
CREATE TABLE files (
|
||||
hash character varying(64) NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
created_by text NOT NULL,
|
||||
created_by uuid NOT NULL,
|
||||
mimetype character varying(64) NOT NULL,
|
||||
data bytea NOT NULL
|
||||
);
|
||||
|
@ -101,25 +95,30 @@ CREATE TABLE licenses (
|
|||
created_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE licenses_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE licenses_id_seq OWNED BY public.licenses.id;
|
||||
|
||||
CREATE TABLE organization_members (
|
||||
organization_id text NOT NULL,
|
||||
user_id text NOT NULL,
|
||||
user_id uuid NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
roles text[] DEFAULT '{organization-member}'::text[] NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE organizations (
|
||||
id text NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
name text NOT NULL,
|
||||
description text NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
"default" boolean DEFAULT false NOT NULL,
|
||||
auto_off_threshold bigint DEFAULT '28800000000000'::bigint NOT NULL,
|
||||
cpu_provisioning_rate real DEFAULT 4.0 NOT NULL,
|
||||
memory_provisioning_rate real DEFAULT 1.0 NOT NULL,
|
||||
workspace_auto_off boolean DEFAULT false NOT NULL
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE parameter_schemas (
|
||||
|
@ -146,7 +145,7 @@ CREATE TABLE parameter_values (
|
|||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
scope parameter_scope NOT NULL,
|
||||
scope_id text NOT NULL,
|
||||
scope_id uuid NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
source_scheme parameter_source_scheme NOT NULL,
|
||||
source_value text NOT NULL,
|
||||
|
@ -156,7 +155,7 @@ CREATE TABLE parameter_values (
|
|||
CREATE TABLE project_versions (
|
||||
id uuid NOT NULL,
|
||||
project_id uuid,
|
||||
organization_id text NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
|
@ -168,7 +167,7 @@ CREATE TABLE projects (
|
|||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
organization_id text NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
deleted boolean DEFAULT false NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
|
@ -179,7 +178,7 @@ CREATE TABLE provisioner_daemons (
|
|||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone,
|
||||
organization_id text,
|
||||
organization_id uuid,
|
||||
name character varying(64) NOT NULL,
|
||||
provisioners provisioner_type[] NOT NULL
|
||||
);
|
||||
|
@ -202,8 +201,8 @@ CREATE TABLE provisioner_jobs (
|
|||
canceled_at timestamp with time zone,
|
||||
completed_at timestamp with time zone,
|
||||
error text,
|
||||
organization_id text NOT NULL,
|
||||
initiator_id text NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
initiator_id uuid NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
storage_method provisioner_storage_method NOT NULL,
|
||||
storage_source text NOT NULL,
|
||||
|
@ -213,7 +212,7 @@ CREATE TABLE provisioner_jobs (
|
|||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
id text NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
email text NOT NULL,
|
||||
name text NOT NULL,
|
||||
revoked boolean NOT NULL,
|
||||
|
@ -221,17 +220,7 @@ CREATE TABLE users (
|
|||
hashed_password bytea NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
temporary_password boolean DEFAULT false NOT NULL,
|
||||
avatar_hash text DEFAULT ''::text NOT NULL,
|
||||
ssh_key_regenerated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
username text DEFAULT ''::text NOT NULL,
|
||||
dotfiles_git_uri text DEFAULT ''::text NOT NULL,
|
||||
roles text[] DEFAULT '{site-member}'::text[] NOT NULL,
|
||||
status userstatus DEFAULT 'active'::public.userstatus NOT NULL,
|
||||
relatime timestamp with time zone DEFAULT now() NOT NULL,
|
||||
gpg_key_regenerated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
_decomissioned boolean DEFAULT false NOT NULL,
|
||||
shell text DEFAULT ''::text NOT NULL
|
||||
username text DEFAULT ''::text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_agents (
|
||||
|
@ -260,7 +249,7 @@ CREATE TABLE workspace_builds (
|
|||
before_id uuid,
|
||||
after_id uuid,
|
||||
transition workspace_transition NOT NULL,
|
||||
initiator character varying(255) NOT NULL,
|
||||
initiator_id uuid NOT NULL,
|
||||
provisioner_state bytea,
|
||||
job_id uuid NOT NULL
|
||||
);
|
||||
|
@ -280,85 +269,136 @@ CREATE TABLE workspaces (
|
|||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
owner_id text NOT NULL,
|
||||
owner_id uuid NOT NULL,
|
||||
project_id uuid NOT NULL,
|
||||
deleted boolean DEFAULT false NOT NULL,
|
||||
name character varying(64) NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY files
|
||||
ADD CONSTRAINT files_hash_key UNIQUE (hash);
|
||||
ALTER TABLE ONLY licenses ALTER COLUMN id SET DEFAULT nextval('public.licenses_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY parameter_schemas
|
||||
ADD CONSTRAINT parameter_schemas_id_key UNIQUE (id);
|
||||
ALTER TABLE ONLY api_keys
|
||||
ADD CONSTRAINT api_keys_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY files
|
||||
ADD CONSTRAINT files_pkey PRIMARY KEY (hash);
|
||||
|
||||
ALTER TABLE ONLY licenses
|
||||
ADD CONSTRAINT licenses_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY organization_members
|
||||
ADD CONSTRAINT organization_members_pkey PRIMARY KEY (organization_id, user_id);
|
||||
|
||||
ALTER TABLE ONLY organizations
|
||||
ADD CONSTRAINT organizations_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY parameter_schemas
|
||||
ADD CONSTRAINT parameter_schemas_job_id_name_key UNIQUE (job_id, name);
|
||||
|
||||
ALTER TABLE ONLY parameter_schemas
|
||||
ADD CONSTRAINT parameter_schemas_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY parameter_values
|
||||
ADD CONSTRAINT parameter_values_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT parameter_values_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY parameter_values
|
||||
ADD CONSTRAINT parameter_values_scope_id_name_key UNIQUE (scope_id, name);
|
||||
|
||||
ALTER TABLE ONLY project_versions
|
||||
ADD CONSTRAINT project_versions_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT project_versions_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY project_versions
|
||||
ADD CONSTRAINT project_versions_project_id_name_key UNIQUE (project_id, name);
|
||||
|
||||
ALTER TABLE ONLY projects
|
||||
ADD CONSTRAINT projects_id_key UNIQUE (id);
|
||||
|
||||
ALTER TABLE ONLY projects
|
||||
ADD CONSTRAINT projects_organization_id_name_key UNIQUE (organization_id, name);
|
||||
|
||||
ALTER TABLE ONLY provisioner_daemons
|
||||
ADD CONSTRAINT provisioner_daemons_id_key UNIQUE (id);
|
||||
ALTER TABLE ONLY projects
|
||||
ADD CONSTRAINT projects_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY provisioner_daemons
|
||||
ADD CONSTRAINT provisioner_daemons_name_key UNIQUE (name);
|
||||
|
||||
ALTER TABLE ONLY provisioner_daemons
|
||||
ADD CONSTRAINT provisioner_daemons_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY provisioner_job_logs
|
||||
ADD CONSTRAINT provisioner_job_logs_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT provisioner_job_logs_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY provisioner_jobs
|
||||
ADD CONSTRAINT provisioner_jobs_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT provisioner_jobs_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY users
|
||||
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY workspace_agents
|
||||
ADD CONSTRAINT workspace_agents_auth_token_key UNIQUE (auth_token);
|
||||
|
||||
ALTER TABLE ONLY workspace_agents
|
||||
ADD CONSTRAINT workspace_agents_id_key UNIQUE (id);
|
||||
|
||||
ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT workspace_agents_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id);
|
||||
|
||||
ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_workspace_id_name_key UNIQUE (workspace_id, name);
|
||||
|
||||
ALTER TABLE ONLY workspace_resources
|
||||
ADD CONSTRAINT workspace_resources_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY workspaces
|
||||
ADD CONSTRAINT workspaces_id_key UNIQUE (id);
|
||||
ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE INDEX idx_api_keys_user ON api_keys USING btree (user_id);
|
||||
|
||||
CREATE INDEX idx_organization_member_organization_id_uuid ON organization_members USING btree (organization_id);
|
||||
|
||||
CREATE INDEX idx_organization_member_user_id_uuid ON organization_members USING btree (user_id);
|
||||
|
||||
CREATE UNIQUE INDEX idx_organization_name ON organizations USING btree (name);
|
||||
|
||||
CREATE UNIQUE INDEX idx_organization_name_lower ON organizations USING btree (lower(name));
|
||||
|
||||
CREATE UNIQUE INDEX idx_users_email ON users USING btree (email);
|
||||
|
||||
CREATE UNIQUE INDEX idx_users_username ON users USING btree (username);
|
||||
|
||||
CREATE UNIQUE INDEX projects_organization_id_name_idx ON projects USING btree (organization_id, name) WHERE (deleted = false);
|
||||
|
||||
CREATE UNIQUE INDEX users_username_lower_idx ON users USING btree (lower(username));
|
||||
|
||||
CREATE UNIQUE INDEX workspaces_owner_id_name_idx ON workspaces USING btree (owner_id, name) WHERE (deleted = false);
|
||||
|
||||
ALTER TABLE ONLY api_keys
|
||||
ADD CONSTRAINT api_keys_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY organization_members
|
||||
ADD CONSTRAINT organization_members_organization_id_uuid_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY organization_members
|
||||
ADD CONSTRAINT organization_members_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY parameter_schemas
|
||||
ADD CONSTRAINT parameter_schemas_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY project_versions
|
||||
ADD CONSTRAINT project_versions_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id);
|
||||
ADD CONSTRAINT project_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY project_versions
|
||||
ADD CONSTRAINT project_versions_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY projects
|
||||
ADD CONSTRAINT projects_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY provisioner_job_logs
|
||||
ADD CONSTRAINT provisioner_job_logs_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY provisioner_jobs
|
||||
ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY workspace_agents
|
||||
ADD CONSTRAINT workspace_agents_resource_id_fkey FOREIGN KEY (resource_id) REFERENCES workspace_resources(id) ON DELETE CASCADE;
|
||||
|
||||
|
@ -375,5 +415,8 @@ ALTER TABLE ONLY workspace_resources
|
|||
ADD CONSTRAINT workspace_resources_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY workspaces
|
||||
ADD CONSTRAINT workspaces_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id);
|
||||
ADD CONSTRAINT workspaces_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
|
||||
ALTER TABLE ONLY workspaces
|
||||
ADD CONSTRAINT workspaces_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE RESTRICT;
|
||||
|
||||
|
|
|
@ -19,14 +19,17 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
defer closeFn()
|
||||
|
||||
db, err := sql.Open("postgres", connection)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = database.MigrateUp(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(
|
||||
"pg_dump",
|
||||
"--schema-only",
|
||||
|
@ -39,10 +42,11 @@ func main() {
|
|||
// queries executing against this table.
|
||||
"--exclude-table=schema_migrations",
|
||||
)
|
||||
cmd.Env = []string{
|
||||
|
||||
cmd.Env = append(os.Environ(), []string{
|
||||
"PGTZ=UTC",
|
||||
"PGCLIENTENCODING=UTF8",
|
||||
}
|
||||
}...)
|
||||
var output bytes.Buffer
|
||||
cmd.Stdout = &output
|
||||
cmd.Stderr = os.Stderr
|
||||
|
@ -57,7 +61,7 @@ func main() {
|
|||
// Public is implicit in the schema.
|
||||
"s/ public\\./ /",
|
||||
// Remove database settings.
|
||||
"s/SET.*;//g",
|
||||
"s/SET .* = .*;//g",
|
||||
// Remove select statements. These aren't useful
|
||||
// to a reader of the dump.
|
||||
"s/SELECT.*;//g",
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
DROP TABLE licenses;
|
||||
DROP TABLE api_keys;
|
||||
DROP TABLE organization_members;
|
||||
DROP TABLE organizations;
|
||||
DROP TABLE users;
|
||||
|
||||
DROP TYPE login_type;
|
||||
|
|
@ -4,28 +4,18 @@
|
|||
-- All tables and types are stolen from:
|
||||
-- https://github.com/coder/m/blob/47b6fc383347b9f9fab424d829c482defd3e1fe2/product/coder/pkg/database/dump.sql
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE login_type AS ENUM (
|
||||
'built-in',
|
||||
'saml',
|
||||
'oidc'
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--
|
||||
-- Name: users; Type: TABLE; Schema: public; Owner: coder
|
||||
--
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE userstatus AS ENUM (
|
||||
'active',
|
||||
'dormant',
|
||||
'decommissioned'
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
CREATE TYPE login_type AS ENUM (
|
||||
'built-in',
|
||||
'saml',
|
||||
'oidc'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id text NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
email text NOT NULL,
|
||||
name text NOT NULL,
|
||||
revoked boolean NOT NULL,
|
||||
|
@ -33,44 +23,51 @@ CREATE TABLE IF NOT EXISTS users (
|
|||
hashed_password bytea NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
temporary_password boolean DEFAULT false NOT NULL,
|
||||
avatar_hash text DEFAULT '' :: text NOT NULL,
|
||||
ssh_key_regenerated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
username text DEFAULT '' :: text NOT NULL,
|
||||
dotfiles_git_uri text DEFAULT '' :: text NOT NULL,
|
||||
roles text [] DEFAULT '{site-member}' :: text [] NOT NULL,
|
||||
status userstatus DEFAULT 'active' :: public.userstatus NOT NULL,
|
||||
relatime timestamp with time zone DEFAULT now() NOT NULL,
|
||||
gpg_key_regenerated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
_decomissioned boolean DEFAULT false NOT NULL,
|
||||
shell text DEFAULT '' :: text NOT NULL
|
||||
username text DEFAULT ''::text NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users USING btree (email);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_username ON users USING btree (username);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS users_username_lower_idx ON users USING btree (lower(username));
|
||||
|
||||
--
|
||||
-- Name: organizations; Type: TABLE; Schema: Owner: coder
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS organizations (
|
||||
id text NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
name text NOT NULL,
|
||||
description text NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
"default" boolean DEFAULT false NOT NULL,
|
||||
auto_off_threshold bigint DEFAULT '28800000000000' :: bigint NOT NULL,
|
||||
cpu_provisioning_rate real DEFAULT 4.0 NOT NULL,
|
||||
memory_provisioning_rate real DEFAULT 1.0 NOT NULL,
|
||||
workspace_auto_off boolean DEFAULT false NOT NULL
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_organization_name ON organizations USING btree (name);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_organization_name_lower ON organizations USING btree (lower(name));
|
||||
|
||||
CREATE TABLE IF NOT EXISTS organization_members (
|
||||
organization_id text NOT NULL,
|
||||
user_id text NOT NULL,
|
||||
user_id uuid NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
roles text [] DEFAULT '{organization-member}' :: text [] NOT NULL
|
||||
roles text [] DEFAULT '{organization-member}' :: text [] NOT NULL,
|
||||
PRIMARY KEY (organization_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_organization_member_organization_id_uuid ON organization_members USING btree (organization_id);
|
||||
CREATE INDEX idx_organization_member_user_id_uuid ON organization_members USING btree (user_id);
|
||||
|
||||
ALTER TABLE ONLY organization_members
|
||||
ADD CONSTRAINT organization_members_organization_id_uuid_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ALTER TABLE ONLY organization_members
|
||||
ADD CONSTRAINT organization_members_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS api_keys (
|
||||
id text NOT NULL,
|
||||
hashed_secret bytea NOT NULL,
|
||||
user_id text NOT NULL,
|
||||
user_id uuid NOT NULL,
|
||||
application boolean NOT NULL,
|
||||
name text NOT NULL,
|
||||
last_used timestamp with time zone NOT NULL,
|
||||
|
@ -82,11 +79,18 @@ CREATE TABLE IF NOT EXISTS api_keys (
|
|||
oidc_refresh_token text DEFAULT ''::text NOT NULL,
|
||||
oidc_id_token text DEFAULT ''::text NOT NULL,
|
||||
oidc_expiry timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL,
|
||||
devurl_token boolean DEFAULT false NOT NULL
|
||||
devurl_token boolean DEFAULT false NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_user ON api_keys USING btree (user_id);
|
||||
|
||||
ALTER TABLE ONLY api_keys
|
||||
ADD CONSTRAINT api_keys_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS licenses (
|
||||
id integer NOT NULL,
|
||||
id serial,
|
||||
license jsonb NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL
|
||||
created_at timestamptz NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
-- Store arbitrary data like project source code or avatars.
|
||||
CREATE TABLE files (
|
||||
hash varchar(64) NOT NULL UNIQUE,
|
||||
hash varchar(64) NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
created_by text NOT NULL,
|
||||
-- foreign key?
|
||||
created_by uuid NOT NULL,
|
||||
mimetype varchar(64) NOT NULL,
|
||||
data bytea NOT NULL
|
||||
data bytea NOT NULL,
|
||||
PRIMARY KEY (hash)
|
||||
);
|
||||
|
||||
CREATE TYPE provisioner_type AS ENUM ('echo', 'terraform');
|
||||
|
@ -12,17 +14,18 @@ CREATE TYPE provisioner_type AS ENUM ('echo', 'terraform');
|
|||
-- Project defines infrastructure that your software project
|
||||
-- requires for development.
|
||||
CREATE TABLE projects (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
-- Projects must be scoped to an organization.
|
||||
organization_id text NOT NULL,
|
||||
organization_id uuid NOT NULL REFERENCES organizations (id) ON DELETE CASCADE,
|
||||
deleted boolean NOT NULL DEFAULT FALSE,
|
||||
name varchar(64) NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
-- Target's a Project Version to use for Workspaces.
|
||||
-- If a Workspace doesn't match this version, it will be prompted to rebuild.
|
||||
active_version_id uuid NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
-- Disallow projects to have the same name under
|
||||
-- the same organization.
|
||||
UNIQUE(organization_id, name)
|
||||
|
@ -35,10 +38,10 @@ CREATE UNIQUE INDEX ON projects (organization_id, name) WHERE deleted = FALSE;
|
|||
-- an "import" job is queued to parse parameters. A Project Version
|
||||
-- can only be used if the import job succeeds.
|
||||
CREATE TABLE project_versions (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
-- This should be indexed.
|
||||
project_id uuid REFERENCES projects (id),
|
||||
organization_id text NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
-- This should be indexed. It is intentionally nullable.
|
||||
project_id uuid REFERENCES projects (id) ON DELETE CASCADE,
|
||||
organization_id uuid NOT NULL REFERENCES organizations (id) ON DELETE CASCADE,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
-- Name is generated for ease of differentiation.
|
||||
|
@ -49,6 +52,7 @@ CREATE TABLE project_versions (
|
|||
description varchar(1048576) NOT NULL,
|
||||
-- The job ID for building the project version.
|
||||
job_id uuid NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
-- Disallow projects to have the same build name
|
||||
-- multiple times.
|
||||
UNIQUE(project_id, name)
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
CREATE TABLE workspaces (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
owner_id text NOT NULL,
|
||||
project_id uuid NOT NULL REFERENCES projects (id),
|
||||
-- Use ON DELETE RESTRICT so that we can cleanup external workspace
|
||||
-- resources first.
|
||||
owner_id uuid NOT NULL REFERENCES users (id) ON DELETE RESTRICT,
|
||||
project_id uuid NOT NULL REFERENCES projects (id) ON DELETE RESTRICT,
|
||||
deleted boolean NOT NULL DEFAULT FALSE,
|
||||
name varchar(64) NOT NULL
|
||||
name varchar(64) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
-- Enforces no active workspaces have the same name.
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
CREATE TABLE IF NOT EXISTS provisioner_daemons (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz,
|
||||
organization_id text,
|
||||
organization_id uuid,
|
||||
-- Name is generated for ease of differentiation.
|
||||
-- eg. WowBananas16
|
||||
name varchar(64) NOT NULL UNIQUE,
|
||||
provisioners provisioner_type [ ] NOT NULL
|
||||
provisioners provisioner_type [ ] NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TYPE provisioner_job_type AS ENUM (
|
||||
|
@ -17,21 +18,23 @@ CREATE TYPE provisioner_job_type AS ENUM (
|
|||
CREATE TYPE provisioner_storage_method AS ENUM ('file');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS provisioner_jobs (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
started_at timestamptz,
|
||||
canceled_at timestamptz,
|
||||
completed_at timestamptz,
|
||||
error text,
|
||||
organization_id text NOT NULL,
|
||||
initiator_id text NOT NULL,
|
||||
organization_id uuid NOT NULL REFERENCES organizations (id) ON DELETE CASCADE,
|
||||
-- foreign key?
|
||||
initiator_id uuid NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
storage_method provisioner_storage_method NOT NULL,
|
||||
storage_source text NOT NULL,
|
||||
type provisioner_job_type NOT NULL,
|
||||
input jsonb NOT NULL,
|
||||
worker_id uuid
|
||||
worker_id uuid,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TYPE log_level AS ENUM (
|
||||
|
@ -48,28 +51,30 @@ CREATE TYPE log_source AS ENUM (
|
|||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS provisioner_job_logs (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
job_id uuid NOT NULL REFERENCES provisioner_jobs (id) ON DELETE CASCADE,
|
||||
created_at timestamptz NOT NULL,
|
||||
source log_source NOT NULL,
|
||||
level log_level NOT NULL,
|
||||
stage varchar(128) NOT NULL,
|
||||
output varchar(1024) NOT NULL
|
||||
output varchar(1024) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_resources (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
job_id uuid NOT NULL REFERENCES provisioner_jobs (id) ON DELETE CASCADE,
|
||||
transition workspace_transition NOT NULL,
|
||||
address varchar(256) NOT NULL,
|
||||
type varchar(192) NOT NULL,
|
||||
name varchar(64) NOT NULL,
|
||||
agent_id uuid
|
||||
agent_id uuid,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_agents (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
first_connected_at timestamptz,
|
||||
|
@ -81,7 +86,8 @@ CREATE TABLE workspace_agents (
|
|||
environment_variables jsonb,
|
||||
startup_script varchar(65534),
|
||||
instance_metadata jsonb,
|
||||
resource_metadata jsonb
|
||||
resource_metadata jsonb,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TYPE parameter_scope AS ENUM (
|
||||
|
@ -111,7 +117,7 @@ CREATE TYPE parameter_destination_scheme AS ENUM('none', 'environment_variable',
|
|||
-- a UI for users to enter values.
|
||||
-- Needs to be made consistent with the examples below.
|
||||
CREATE TABLE parameter_schemas (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
job_id uuid NOT NULL REFERENCES provisioner_jobs (id) ON DELETE CASCADE,
|
||||
name varchar(64) NOT NULL,
|
||||
|
@ -131,26 +137,28 @@ CREATE TABLE parameter_schemas (
|
|||
validation_condition varchar(512) NOT NULL,
|
||||
validation_type_system parameter_type_system NOT NULL,
|
||||
validation_value_type varchar(64) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE(job_id, name)
|
||||
);
|
||||
|
||||
-- Parameters are provided to jobs for provisioning and to workspaces.
|
||||
CREATE TABLE parameter_values (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
scope parameter_scope NOT NULL,
|
||||
scope_id text NOT NULL,
|
||||
scope_id uuid NOT NULL,
|
||||
name varchar(64) NOT NULL,
|
||||
source_scheme parameter_source_scheme NOT NULL,
|
||||
source_value text NOT NULL,
|
||||
destination_scheme parameter_destination_scheme NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
-- Prevents duplicates for parameters in the same scope.
|
||||
UNIQUE(scope_id, name)
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_builds (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
workspace_id uuid NOT NULL REFERENCES workspaces (id) ON DELETE CASCADE,
|
||||
|
@ -159,10 +167,11 @@ CREATE TABLE workspace_builds (
|
|||
before_id uuid,
|
||||
after_id uuid,
|
||||
transition workspace_transition NOT NULL,
|
||||
initiator varchar(255) NOT NULL,
|
||||
initiator_id uuid NOT NULL,
|
||||
-- State stored by the provisioner
|
||||
provisioner_state bytea,
|
||||
-- Job ID of the action
|
||||
job_id uuid NOT NULL UNIQUE REFERENCES provisioner_jobs (id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE(workspace_id, name)
|
||||
);
|
||||
|
|
|
@ -209,26 +209,6 @@ func (e *ProvisionerType) Scan(src interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type UserStatus string
|
||||
|
||||
const (
|
||||
UserstatusActive UserStatus = "active"
|
||||
UserstatusDormant UserStatus = "dormant"
|
||||
UserstatusDecommissioned UserStatus = "decommissioned"
|
||||
)
|
||||
|
||||
func (e *UserStatus) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = UserStatus(s)
|
||||
case string:
|
||||
*e = UserStatus(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for UserStatus: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type WorkspaceTransition string
|
||||
|
||||
const (
|
||||
|
@ -252,7 +232,7 @@ func (e *WorkspaceTransition) Scan(src interface{}) error {
|
|||
type APIKey struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
Application bool `db:"application" json:"application"`
|
||||
Name string `db:"name" json:"name"`
|
||||
LastUsed time.Time `db:"last_used" json:"last_used"`
|
||||
|
@ -270,7 +250,7 @@ type APIKey struct {
|
|||
type File struct {
|
||||
Hash string `db:"hash" json:"hash"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
CreatedBy string `db:"created_by" json:"created_by"`
|
||||
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
|
||||
Mimetype string `db:"mimetype" json:"mimetype"`
|
||||
Data []byte `db:"data" json:"data"`
|
||||
}
|
||||
|
@ -282,21 +262,16 @@ type License struct {
|
|||
}
|
||||
|
||||
type Organization struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Description string `db:"description" json:"description"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Default bool `db:"default" json:"default"`
|
||||
AutoOffThreshold int64 `db:"auto_off_threshold" json:"auto_off_threshold"`
|
||||
CpuProvisioningRate float32 `db:"cpu_provisioning_rate" json:"cpu_provisioning_rate"`
|
||||
MemoryProvisioningRate float32 `db:"memory_provisioning_rate" json:"memory_provisioning_rate"`
|
||||
WorkspaceAutoOff bool `db:"workspace_auto_off" json:"workspace_auto_off"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Description string `db:"description" json:"description"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
}
|
||||
|
||||
type OrganizationMember struct {
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Roles []string `db:"roles" json:"roles"`
|
||||
|
@ -326,7 +301,7 @@ type ParameterValue struct {
|
|||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Scope ParameterScope `db:"scope" json:"scope"`
|
||||
ScopeID string `db:"scope_id" json:"scope_id"`
|
||||
ScopeID uuid.UUID `db:"scope_id" json:"scope_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
SourceScheme ParameterSourceScheme `db:"source_scheme" json:"source_scheme"`
|
||||
SourceValue string `db:"source_value" json:"source_value"`
|
||||
|
@ -337,7 +312,7 @@ type Project struct {
|
|||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
|
@ -347,7 +322,7 @@ type Project struct {
|
|||
type ProjectVersion struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
ProjectID uuid.NullUUID `db:"project_id" json:"project_id"`
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
|
@ -359,7 +334,7 @@ type ProvisionerDaemon struct {
|
|||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
|
||||
OrganizationID sql.NullString `db:"organization_id" json:"organization_id"`
|
||||
OrganizationID uuid.NullUUID `db:"organization_id" json:"organization_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioners []ProvisionerType `db:"provisioners" json:"provisioners"`
|
||||
}
|
||||
|
@ -372,8 +347,8 @@ type ProvisionerJob struct {
|
|||
CanceledAt sql.NullTime `db:"canceled_at" json:"canceled_at"`
|
||||
CompletedAt sql.NullTime `db:"completed_at" json:"completed_at"`
|
||||
Error sql.NullString `db:"error" json:"error"`
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
InitiatorID string `db:"initiator_id" json:"initiator_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
StorageMethod ProvisionerStorageMethod `db:"storage_method" json:"storage_method"`
|
||||
StorageSource string `db:"storage_source" json:"storage_source"`
|
||||
|
@ -393,32 +368,22 @@ type ProvisionerJobLog struct {
|
|||
}
|
||||
|
||||
type User struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Revoked bool `db:"revoked" json:"revoked"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
HashedPassword []byte `db:"hashed_password" json:"hashed_password"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
TemporaryPassword bool `db:"temporary_password" json:"temporary_password"`
|
||||
AvatarHash string `db:"avatar_hash" json:"avatar_hash"`
|
||||
SshKeyRegeneratedAt time.Time `db:"ssh_key_regenerated_at" json:"ssh_key_regenerated_at"`
|
||||
Username string `db:"username" json:"username"`
|
||||
DotfilesGitUri string `db:"dotfiles_git_uri" json:"dotfiles_git_uri"`
|
||||
Roles []string `db:"roles" json:"roles"`
|
||||
Status UserStatus `db:"status" json:"status"`
|
||||
Relatime time.Time `db:"relatime" json:"relatime"`
|
||||
GpgKeyRegeneratedAt time.Time `db:"gpg_key_regenerated_at" json:"gpg_key_regenerated_at"`
|
||||
Decomissioned bool `db:"_decomissioned" json:"_decomissioned"`
|
||||
Shell string `db:"shell" json:"shell"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Revoked bool `db:"revoked" json:"revoked"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
HashedPassword []byte `db:"hashed_password" json:"hashed_password"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Username string `db:"username" json:"username"`
|
||||
}
|
||||
|
||||
type Workspace struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OwnerID string `db:"owner_id" json:"owner_id"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
ProjectID uuid.UUID `db:"project_id" json:"project_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
|
@ -450,7 +415,7 @@ type WorkspaceBuild struct {
|
|||
BeforeID uuid.NullUUID `db:"before_id" json:"before_id"`
|
||||
AfterID uuid.NullUUID `db:"after_id" json:"after_id"`
|
||||
Transition WorkspaceTransition `db:"transition" json:"transition"`
|
||||
Initiator string `db:"initiator" json:"initiator"`
|
||||
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
|
||||
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
|
||||
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -31,15 +32,18 @@ func Open() (string, func(), error) {
|
|||
return "", nil, xerrors.Errorf("connect to ci postgres: %w", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
dbName, err := cryptorand.StringCharset(cryptorand.Lower, 10)
|
||||
if err != nil {
|
||||
return "", nil, xerrors.Errorf("generate db name: %w", err)
|
||||
}
|
||||
|
||||
dbName = "ci" + dbName
|
||||
_, err = db.Exec("CREATE DATABASE " + dbName)
|
||||
if err != nil {
|
||||
return "", nil, xerrors.Errorf("create db: %w", err)
|
||||
}
|
||||
|
||||
return "postgres://postgres:postgres@127.0.0.1:5432/" + dbName + "?sslmode=disable", func() {}, nil
|
||||
}
|
||||
|
||||
|
@ -59,7 +63,7 @@ func Open() (string, func(), error) {
|
|||
port, err := getFreePort()
|
||||
if err != nil {
|
||||
openPortMutex.Unlock()
|
||||
return "", nil, xerrors.Errorf("Unable to get free port: %w", err)
|
||||
return "", nil, xerrors.Errorf("get free port: %w", err)
|
||||
}
|
||||
|
||||
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
|
||||
|
@ -80,7 +84,8 @@ func Open() (string, func(), error) {
|
|||
// https://github.com/moby/moby/issues/42442
|
||||
// where the ipv4 and ipv6 ports might be _different_ and collide with other running docker containers.
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: fmt.Sprintf("%d", port)}},
|
||||
HostPort: strconv.FormatInt(int64(port), 10),
|
||||
}},
|
||||
},
|
||||
Mounts: []string{
|
||||
// The postgres image has a VOLUME parameter in it's image.
|
||||
|
@ -107,18 +112,23 @@ func Open() (string, func(), error) {
|
|||
// Docker should hard-kill the container after 120 seconds.
|
||||
err = resource.Expire(120)
|
||||
if err != nil {
|
||||
return "", nil, xerrors.Errorf("could not expire resource: %w", err)
|
||||
return "", nil, xerrors.Errorf("expire resource: %w", err)
|
||||
}
|
||||
|
||||
pool.MaxWait = 120 * time.Second
|
||||
err = pool.Retry(func() error {
|
||||
db, err := sql.Open("postgres", dbURL)
|
||||
if err != nil {
|
||||
return err
|
||||
return xerrors.Errorf("open postgres: %w", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Ping()
|
||||
_ = db.Close()
|
||||
return err
|
||||
if err != nil {
|
||||
return xerrors.Errorf("ping postgres: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
|
|
@ -13,10 +13,10 @@ type querier interface {
|
|||
DeleteParameterValueByID(ctx context.Context, id uuid.UUID) error
|
||||
GetAPIKeyByID(ctx context.Context, id string) (APIKey, error)
|
||||
GetFileByHash(ctx context.Context, hash string) (File, error)
|
||||
GetOrganizationByID(ctx context.Context, id string) (Organization, error)
|
||||
GetOrganizationByID(ctx context.Context, id uuid.UUID) (Organization, error)
|
||||
GetOrganizationByName(ctx context.Context, name string) (Organization, error)
|
||||
GetOrganizationMemberByUserID(ctx context.Context, arg GetOrganizationMemberByUserIDParams) (OrganizationMember, error)
|
||||
GetOrganizationsByUserID(ctx context.Context, userID string) ([]Organization, error)
|
||||
GetOrganizationsByUserID(ctx context.Context, userID uuid.UUID) ([]Organization, error)
|
||||
GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUID) ([]ParameterSchema, error)
|
||||
GetParameterValueByScopeAndName(ctx context.Context, arg GetParameterValueByScopeAndNameParams) (ParameterValue, error)
|
||||
GetParameterValuesByScope(ctx context.Context, arg GetParameterValuesByScopeParams) ([]ParameterValue, error)
|
||||
|
@ -34,7 +34,7 @@ type querier interface {
|
|||
GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID) ([]ProvisionerJob, error)
|
||||
GetProvisionerLogsByIDBetween(ctx context.Context, arg GetProvisionerLogsByIDBetweenParams) ([]ProvisionerJobLog, error)
|
||||
GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error)
|
||||
GetUserByID(ctx context.Context, id string) (User, error)
|
||||
GetUserByID(ctx context.Context, id uuid.UUID) (User, error)
|
||||
GetUserCount(ctx context.Context) (int64, error)
|
||||
GetWorkspaceAgentByAuthToken(ctx context.Context, authToken uuid.UUID) (WorkspaceAgent, error)
|
||||
GetWorkspaceAgentByInstanceID(ctx context.Context, authInstanceID string) (WorkspaceAgent, error)
|
||||
|
|
|
@ -683,7 +683,7 @@ INSERT INTO
|
|||
before_id,
|
||||
name,
|
||||
transition,
|
||||
initiator,
|
||||
initiator_id,
|
||||
job_id,
|
||||
provisioner_state
|
||||
)
|
||||
|
|
|
@ -148,14 +148,14 @@ func (q *sqlQuerier) GetFileByHash(ctx context.Context, hash string) (File, erro
|
|||
|
||||
const getOrganizationByID = `-- name: GetOrganizationByID :one
|
||||
SELECT
|
||||
id, name, description, created_at, updated_at, "default", auto_off_threshold, cpu_provisioning_rate, memory_provisioning_rate, workspace_auto_off
|
||||
id, name, description, created_at, updated_at
|
||||
FROM
|
||||
organizations
|
||||
WHERE
|
||||
id = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetOrganizationByID(ctx context.Context, id string) (Organization, error) {
|
||||
func (q *sqlQuerier) GetOrganizationByID(ctx context.Context, id uuid.UUID) (Organization, error) {
|
||||
row := q.db.QueryRowContext(ctx, getOrganizationByID, id)
|
||||
var i Organization
|
||||
err := row.Scan(
|
||||
|
@ -164,18 +164,13 @@ func (q *sqlQuerier) GetOrganizationByID(ctx context.Context, id string) (Organi
|
|||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Default,
|
||||
&i.AutoOffThreshold,
|
||||
&i.CpuProvisioningRate,
|
||||
&i.MemoryProvisioningRate,
|
||||
&i.WorkspaceAutoOff,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getOrganizationByName = `-- name: GetOrganizationByName :one
|
||||
SELECT
|
||||
id, name, description, created_at, updated_at, "default", auto_off_threshold, cpu_provisioning_rate, memory_provisioning_rate, workspace_auto_off
|
||||
id, name, description, created_at, updated_at
|
||||
FROM
|
||||
organizations
|
||||
WHERE
|
||||
|
@ -193,18 +188,13 @@ func (q *sqlQuerier) GetOrganizationByName(ctx context.Context, name string) (Or
|
|||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Default,
|
||||
&i.AutoOffThreshold,
|
||||
&i.CpuProvisioningRate,
|
||||
&i.MemoryProvisioningRate,
|
||||
&i.WorkspaceAutoOff,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getOrganizationMemberByUserID = `-- name: GetOrganizationMemberByUserID :one
|
||||
SELECT
|
||||
organization_id, user_id, created_at, updated_at, roles
|
||||
user_id, organization_id, created_at, updated_at, roles
|
||||
FROM
|
||||
organization_members
|
||||
WHERE
|
||||
|
@ -215,16 +205,16 @@ LIMIT
|
|||
`
|
||||
|
||||
type GetOrganizationMemberByUserIDParams struct {
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetOrganizationMemberByUserID(ctx context.Context, arg GetOrganizationMemberByUserIDParams) (OrganizationMember, error) {
|
||||
row := q.db.QueryRowContext(ctx, getOrganizationMemberByUserID, arg.OrganizationID, arg.UserID)
|
||||
var i OrganizationMember
|
||||
err := row.Scan(
|
||||
&i.OrganizationID,
|
||||
&i.UserID,
|
||||
&i.OrganizationID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
pq.Array(&i.Roles),
|
||||
|
@ -234,7 +224,7 @@ func (q *sqlQuerier) GetOrganizationMemberByUserID(ctx context.Context, arg GetO
|
|||
|
||||
const getOrganizationsByUserID = `-- name: GetOrganizationsByUserID :many
|
||||
SELECT
|
||||
id, name, description, created_at, updated_at, "default", auto_off_threshold, cpu_provisioning_rate, memory_provisioning_rate, workspace_auto_off
|
||||
id, name, description, created_at, updated_at
|
||||
FROM
|
||||
organizations
|
||||
WHERE
|
||||
|
@ -248,7 +238,7 @@ WHERE
|
|||
)
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetOrganizationsByUserID(ctx context.Context, userID string) ([]Organization, error) {
|
||||
func (q *sqlQuerier) GetOrganizationsByUserID(ctx context.Context, userID uuid.UUID) ([]Organization, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getOrganizationsByUserID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -263,11 +253,6 @@ func (q *sqlQuerier) GetOrganizationsByUserID(ctx context.Context, userID string
|
|||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Default,
|
||||
&i.AutoOffThreshold,
|
||||
&i.CpuProvisioningRate,
|
||||
&i.MemoryProvisioningRate,
|
||||
&i.WorkspaceAutoOff,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -346,7 +331,7 @@ LIMIT
|
|||
|
||||
type GetParameterValueByScopeAndNameParams struct {
|
||||
Scope ParameterScope `db:"scope" json:"scope"`
|
||||
ScopeID string `db:"scope_id" json:"scope_id"`
|
||||
ScopeID uuid.UUID `db:"scope_id" json:"scope_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
|
@ -379,7 +364,7 @@ WHERE
|
|||
|
||||
type GetParameterValuesByScopeParams struct {
|
||||
Scope ParameterScope `db:"scope" json:"scope"`
|
||||
ScopeID string `db:"scope_id" json:"scope_id"`
|
||||
ScopeID uuid.UUID `db:"scope_id" json:"scope_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetParameterValuesByScope(ctx context.Context, arg GetParameterValuesByScopeParams) ([]ParameterValue, error) {
|
||||
|
@ -456,9 +441,9 @@ LIMIT
|
|||
`
|
||||
|
||||
type GetProjectByOrganizationAndNameParams struct {
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetProjectByOrganizationAndName(ctx context.Context, arg GetProjectByOrganizationAndNameParams) (Project, error) {
|
||||
|
@ -651,8 +636,8 @@ WHERE
|
|||
`
|
||||
|
||||
type GetProjectsByOrganizationParams struct {
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetProjectsByOrganization(ctx context.Context, arg GetProjectsByOrganizationParams) ([]Project, error) {
|
||||
|
@ -881,7 +866,7 @@ func (q *sqlQuerier) GetProvisionerLogsByIDBetween(ctx context.Context, arg GetP
|
|||
|
||||
const getUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one
|
||||
SELECT
|
||||
id, email, name, revoked, login_type, hashed_password, created_at, updated_at, temporary_password, avatar_hash, ssh_key_regenerated_at, username, dotfiles_git_uri, roles, status, relatime, gpg_key_regenerated_at, _decomissioned, shell
|
||||
id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
|
@ -908,24 +893,14 @@ func (q *sqlQuerier) GetUserByEmailOrUsername(ctx context.Context, arg GetUserBy
|
|||
&i.HashedPassword,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.TemporaryPassword,
|
||||
&i.AvatarHash,
|
||||
&i.SshKeyRegeneratedAt,
|
||||
&i.Username,
|
||||
&i.DotfilesGitUri,
|
||||
pq.Array(&i.Roles),
|
||||
&i.Status,
|
||||
&i.Relatime,
|
||||
&i.GpgKeyRegeneratedAt,
|
||||
&i.Decomissioned,
|
||||
&i.Shell,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserByID = `-- name: GetUserByID :one
|
||||
SELECT
|
||||
id, email, name, revoked, login_type, hashed_password, created_at, updated_at, temporary_password, avatar_hash, ssh_key_regenerated_at, username, dotfiles_git_uri, roles, status, relatime, gpg_key_regenerated_at, _decomissioned, shell
|
||||
id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
|
@ -934,7 +909,7 @@ LIMIT
|
|||
1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetUserByID(ctx context.Context, id string) (User, error) {
|
||||
func (q *sqlQuerier) GetUserByID(ctx context.Context, id uuid.UUID) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserByID, id)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
|
@ -946,17 +921,7 @@ func (q *sqlQuerier) GetUserByID(ctx context.Context, id string) (User, error) {
|
|||
&i.HashedPassword,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.TemporaryPassword,
|
||||
&i.AvatarHash,
|
||||
&i.SshKeyRegeneratedAt,
|
||||
&i.Username,
|
||||
&i.DotfilesGitUri,
|
||||
pq.Array(&i.Roles),
|
||||
&i.Status,
|
||||
&i.Relatime,
|
||||
&i.GpgKeyRegeneratedAt,
|
||||
&i.Decomissioned,
|
||||
&i.Shell,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
@ -1071,7 +1036,7 @@ func (q *sqlQuerier) GetWorkspaceAgentByResourceID(ctx context.Context, resource
|
|||
|
||||
const getWorkspaceBuildByID = `-- name: GetWorkspaceBuildByID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
|
@ -1093,7 +1058,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
)
|
||||
|
@ -1102,7 +1067,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
|
|||
|
||||
const getWorkspaceBuildByJobID = `-- name: GetWorkspaceBuildByJobID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
|
@ -1124,7 +1089,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
)
|
||||
|
@ -1133,7 +1098,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
|
|||
|
||||
const getWorkspaceBuildByWorkspaceID = `-- name: GetWorkspaceBuildByWorkspaceID :many
|
||||
SELECT
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
|
@ -1159,7 +1124,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, workspa
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
); err != nil {
|
||||
|
@ -1178,7 +1143,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceID(ctx context.Context, workspa
|
|||
|
||||
const getWorkspaceBuildByWorkspaceIDAndName = `-- name: GetWorkspaceBuildByWorkspaceIDAndName :one
|
||||
SELECT
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
|
@ -1204,7 +1169,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndName(ctx context.Context,
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
)
|
||||
|
@ -1213,7 +1178,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndName(ctx context.Context,
|
|||
|
||||
const getWorkspaceBuildByWorkspaceIDWithoutAfter = `-- name: GetWorkspaceBuildByWorkspaceIDWithoutAfter :one
|
||||
SELECT
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
|
@ -1236,7 +1201,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDWithoutAfter(ctx context.Cont
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
)
|
||||
|
@ -1245,7 +1210,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDWithoutAfter(ctx context.Cont
|
|||
|
||||
const getWorkspaceBuildsByWorkspaceIDsWithoutAfter = `-- name: GetWorkspaceBuildsByWorkspaceIDsWithoutAfter :many
|
||||
SELECT
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
|
@ -1272,7 +1237,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceIDsWithoutAfter(ctx context.Co
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
); err != nil {
|
||||
|
@ -1327,9 +1292,9 @@ WHERE
|
|||
`
|
||||
|
||||
type GetWorkspaceByUserIDAndNameParams struct {
|
||||
OwnerID string `db:"owner_id" json:"owner_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetWorkspaceByUserIDAndName(ctx context.Context, arg GetWorkspaceByUserIDAndNameParams) (Workspace, error) {
|
||||
|
@ -1511,8 +1476,8 @@ WHERE
|
|||
`
|
||||
|
||||
type GetWorkspacesByUserIDParams struct {
|
||||
OwnerID string `db:"owner_id" json:"owner_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetWorkspacesByUserID(ctx context.Context, arg GetWorkspacesByUserIDParams) ([]Workspace, error) {
|
||||
|
@ -1588,7 +1553,7 @@ VALUES
|
|||
type InsertAPIKeyParams struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
Application bool `db:"application" json:"application"`
|
||||
Name string `db:"name" json:"name"`
|
||||
LastUsed time.Time `db:"last_used" json:"last_used"`
|
||||
|
@ -1652,7 +1617,7 @@ VALUES
|
|||
type InsertFileParams struct {
|
||||
Hash string `db:"hash" json:"hash"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
CreatedBy string `db:"created_by" json:"created_by"`
|
||||
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
|
||||
Mimetype string `db:"mimetype" json:"mimetype"`
|
||||
Data []byte `db:"data" json:"data"`
|
||||
}
|
||||
|
@ -1680,11 +1645,11 @@ const insertOrganization = `-- name: InsertOrganization :one
|
|||
INSERT INTO
|
||||
organizations (id, name, description, created_at, updated_at)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5) RETURNING id, name, description, created_at, updated_at, "default", auto_off_threshold, cpu_provisioning_rate, memory_provisioning_rate, workspace_auto_off
|
||||
($1, $2, $3, $4, $5) RETURNING id, name, description, created_at, updated_at
|
||||
`
|
||||
|
||||
type InsertOrganizationParams struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Description string `db:"description" json:"description"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
|
@ -1706,11 +1671,6 @@ func (q *sqlQuerier) InsertOrganization(ctx context.Context, arg InsertOrganizat
|
|||
&i.Description,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Default,
|
||||
&i.AutoOffThreshold,
|
||||
&i.CpuProvisioningRate,
|
||||
&i.MemoryProvisioningRate,
|
||||
&i.WorkspaceAutoOff,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
@ -1725,12 +1685,12 @@ INSERT INTO
|
|||
roles
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5) RETURNING organization_id, user_id, created_at, updated_at, roles
|
||||
($1, $2, $3, $4, $5) RETURNING user_id, organization_id, created_at, updated_at, roles
|
||||
`
|
||||
|
||||
type InsertOrganizationMemberParams struct {
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Roles []string `db:"roles" json:"roles"`
|
||||
|
@ -1746,8 +1706,8 @@ func (q *sqlQuerier) InsertOrganizationMember(ctx context.Context, arg InsertOrg
|
|||
)
|
||||
var i OrganizationMember
|
||||
err := row.Scan(
|
||||
&i.OrganizationID,
|
||||
&i.UserID,
|
||||
&i.OrganizationID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
pq.Array(&i.Roles),
|
||||
|
@ -1879,7 +1839,7 @@ type InsertParameterValueParams struct {
|
|||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Scope ParameterScope `db:"scope" json:"scope"`
|
||||
ScopeID string `db:"scope_id" json:"scope_id"`
|
||||
ScopeID uuid.UUID `db:"scope_id" json:"scope_id"`
|
||||
SourceScheme ParameterSourceScheme `db:"source_scheme" json:"source_scheme"`
|
||||
SourceValue string `db:"source_value" json:"source_value"`
|
||||
DestinationScheme ParameterDestinationScheme `db:"destination_scheme" json:"destination_scheme"`
|
||||
|
@ -1931,7 +1891,7 @@ type InsertProjectParams struct {
|
|||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
|
@ -1980,7 +1940,7 @@ VALUES
|
|||
type InsertProjectVersionParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
ProjectID uuid.NullUUID `db:"project_id" json:"project_id"`
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
|
@ -2023,7 +1983,7 @@ VALUES
|
|||
type InsertProvisionerDaemonParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
OrganizationID sql.NullString `db:"organization_id" json:"organization_id"`
|
||||
OrganizationID uuid.NullUUID `db:"organization_id" json:"organization_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioners []ProvisionerType `db:"provisioners" json:"provisioners"`
|
||||
}
|
||||
|
@ -2070,8 +2030,8 @@ type InsertProvisionerJobParams struct {
|
|||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OrganizationID string `db:"organization_id" json:"organization_id"`
|
||||
InitiatorID string `db:"initiator_id" json:"initiator_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
StorageMethod ProvisionerStorageMethod `db:"storage_method" json:"storage_method"`
|
||||
StorageSource string `db:"storage_source" json:"storage_source"`
|
||||
|
@ -2189,11 +2149,11 @@ INSERT INTO
|
|||
username
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, false, $5, $6, $7, $8) RETURNING id, email, name, revoked, login_type, hashed_password, created_at, updated_at, temporary_password, avatar_hash, ssh_key_regenerated_at, username, dotfiles_git_uri, roles, status, relatime, gpg_key_regenerated_at, _decomissioned, shell
|
||||
($1, $2, $3, $4, false, $5, $6, $7, $8) RETURNING id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username
|
||||
`
|
||||
|
||||
type InsertUserParams struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Name string `db:"name" json:"name"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
|
@ -2224,17 +2184,7 @@ func (q *sqlQuerier) InsertUser(ctx context.Context, arg InsertUserParams) (User
|
|||
&i.HashedPassword,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.TemporaryPassword,
|
||||
&i.AvatarHash,
|
||||
&i.SshKeyRegeneratedAt,
|
||||
&i.Username,
|
||||
&i.DotfilesGitUri,
|
||||
pq.Array(&i.Roles),
|
||||
&i.Status,
|
||||
&i.Relatime,
|
||||
&i.GpgKeyRegeneratedAt,
|
||||
&i.Decomissioned,
|
||||
&i.Shell,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
@ -2257,7 +2207,7 @@ type InsertWorkspaceParams struct {
|
|||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OwnerID string `db:"owner_id" json:"owner_id"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
ProjectID uuid.UUID `db:"project_id" json:"project_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
@ -2358,12 +2308,12 @@ INSERT INTO
|
|||
before_id,
|
||||
name,
|
||||
transition,
|
||||
initiator,
|
||||
initiator_id,
|
||||
job_id,
|
||||
provisioner_state
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator, provisioner_state, job_id
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, created_at, updated_at, workspace_id, project_version_id, name, before_id, after_id, transition, initiator_id, provisioner_state, job_id
|
||||
`
|
||||
|
||||
type InsertWorkspaceBuildParams struct {
|
||||
|
@ -2375,7 +2325,7 @@ type InsertWorkspaceBuildParams struct {
|
|||
BeforeID uuid.NullUUID `db:"before_id" json:"before_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Transition WorkspaceTransition `db:"transition" json:"transition"`
|
||||
Initiator string `db:"initiator" json:"initiator"`
|
||||
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
|
||||
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
|
||||
}
|
||||
|
@ -2390,7 +2340,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
|
|||
arg.BeforeID,
|
||||
arg.Name,
|
||||
arg.Transition,
|
||||
arg.Initiator,
|
||||
arg.InitiatorID,
|
||||
arg.JobID,
|
||||
arg.ProvisionerState,
|
||||
)
|
||||
|
@ -2405,7 +2355,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
|
|||
&i.BeforeID,
|
||||
&i.AfterID,
|
||||
&i.Transition,
|
||||
&i.Initiator,
|
||||
&i.InitiatorID,
|
||||
&i.ProvisionerState,
|
||||
&i.JobID,
|
||||
)
|
||||
|
|
|
@ -19,6 +19,13 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
|
|||
})
|
||||
return uuid.UUID{}, false
|
||||
}
|
||||
|
||||
// Automatically set uuid.Nil to the acting users id.
|
||||
if param == UserKey && rawID == "me" {
|
||||
key := APIKey(r)
|
||||
return key.UserID, true
|
||||
}
|
||||
|
||||
parsed, err := uuid.Parse(rawID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
|
@ -26,5 +33,6 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
|
|||
})
|
||||
return uuid.UUID{}, false
|
||||
}
|
||||
|
||||
return parsed, true
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
@ -40,17 +38,15 @@ func OrganizationMemberParam(r *http.Request) database.OrganizationMember {
|
|||
func ExtractOrganizationParam(db database.Store) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
organizationID := chi.URLParam(r, "organization")
|
||||
if organizationID == "" {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "organization must be provided",
|
||||
})
|
||||
orgID, ok := parseUUID(rw, r, "organization")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
organization, err := db.GetOrganizationByID(r.Context(), organizationID)
|
||||
|
||||
organization, err := db.GetOrganizationByID(r.Context(), orgID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("organization %q does not exist", organizationID),
|
||||
Message: fmt.Sprintf("organization %q does not exist", orgID),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -60,6 +56,7 @@ func ExtractOrganizationParam(db database.Store) func(http.Handler) http.Handler
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
apiKey := APIKey(r)
|
||||
organizationMember, err := db.GetOrganizationMemberByUserID(r.Context(), database.GetOrganizationMemberByUserIDParams{
|
||||
OrganizationID: organization.ID,
|
||||
|
|
|
@ -32,10 +32,11 @@ func TestOrganizationParam(t *testing.T) {
|
|||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: userID,
|
||||
Email: "testaccount@coder.com",
|
||||
|
@ -86,7 +87,7 @@ func TestOrganizationParam(t *testing.T) {
|
|||
r, _ = setupAuthentication(db)
|
||||
rtr = chi.NewRouter()
|
||||
)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", "nothin")
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", uuid.NewString())
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
|
@ -98,6 +99,26 @@ func TestOrganizationParam(t *testing.T) {
|
|||
require.Equal(t, http.StatusNotFound, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("InvalidUUID", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var (
|
||||
db = databasefake.New()
|
||||
rw = httptest.NewRecorder()
|
||||
r, _ = setupAuthentication(db)
|
||||
rtr = chi.NewRouter()
|
||||
)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", "not-a-uuid")
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
)
|
||||
rtr.Get("/", nil)
|
||||
rtr.ServeHTTP(rw, r)
|
||||
res := rw.Result()
|
||||
defer res.Body.Close()
|
||||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("NotInOrganization", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var (
|
||||
|
@ -107,13 +128,13 @@ func TestOrganizationParam(t *testing.T) {
|
|||
rtr = chi.NewRouter()
|
||||
)
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Name: "test",
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID.String())
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
|
@ -134,7 +155,7 @@ func TestOrganizationParam(t *testing.T) {
|
|||
rtr = chi.NewRouter()
|
||||
)
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Name: "test",
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
|
@ -147,7 +168,7 @@ func TestOrganizationParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID.String())
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
|
|
|
@ -46,7 +46,7 @@ func ExtractProjectParam(db database.Store) func(http.Handler) http.Handler {
|
|||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), projectParamContextKey{}, project)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", project.OrganizationID)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", project.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ func TestProjectParam(t *testing.T) {
|
|||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
|
@ -47,6 +47,7 @@ func TestProjectParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
|
@ -55,8 +56,8 @@ func TestProjectParam(t *testing.T) {
|
|||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
orgID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := uuid.New()
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: orgID,
|
||||
Name: "banana",
|
||||
|
@ -65,6 +66,7 @@ func TestProjectParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertOrganizationMember(r.Context(), database.InsertOrganizationMemberParams{
|
||||
OrganizationID: orgID,
|
||||
UserID: user.ID,
|
||||
|
|
|
@ -47,7 +47,7 @@ func ExtractProjectVersionParam(db database.Store) func(http.Handler) http.Handl
|
|||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), projectVersionParamContextKey{}, projectVersion)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", projectVersion.OrganizationID)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", projectVersion.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ func TestProjectVersionParam(t *testing.T) {
|
|||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
|
@ -47,6 +47,7 @@ func TestProjectVersionParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
|
@ -55,8 +56,8 @@ func TestProjectVersionParam(t *testing.T) {
|
|||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
orgID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := uuid.New()
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: orgID,
|
||||
Name: "banana",
|
||||
|
@ -65,6 +66,7 @@ func TestProjectVersionParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertOrganizationMember(r.Context(), database.InsertOrganizationMemberParams{
|
||||
OrganizationID: orgID,
|
||||
UserID: user.ID,
|
||||
|
@ -72,6 +74,7 @@ func TestProjectVersionParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
project, err := db.InsertProject(context.Background(), database.InsertProjectParams{
|
||||
ID: uuid.New(),
|
||||
OrganizationID: organization.ID,
|
||||
|
|
|
@ -5,12 +5,12 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
||||
const UserKey = "user"
|
||||
|
||||
type userParamContextKey struct{}
|
||||
|
||||
// UserParam returns the user from the ExtractUserParam handler.
|
||||
|
@ -26,21 +26,20 @@ func UserParam(r *http.Request) database.User {
|
|||
func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
userID := chi.URLParam(r, "user")
|
||||
if userID == "" {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "user id or name must be provided",
|
||||
})
|
||||
userID, ok := parseUUID(rw, r, UserKey)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
apiKey := APIKey(r)
|
||||
if apiKey.UserID != userID && userID != "me" {
|
||||
if apiKey.UserID != userID {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "getting non-personal users isn't supported yet",
|
||||
})
|
||||
return
|
||||
}
|
||||
user, err := db.GetUserByID(r.Context(), apiKey.UserID)
|
||||
|
||||
user, err := db.GetUserByID(r.Context(), userID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get user: %s", err.Error()),
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
|
@ -32,18 +33,20 @@ func TestUserParam(t *testing.T) {
|
|||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
|
||||
_, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: "bananas",
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: uuid.New(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: "bananas",
|
||||
UserID: user.ID,
|
||||
HashedSecret: hashed[:],
|
||||
LastUsed: database.Now(),
|
||||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return db, rw, r
|
||||
}
|
||||
|
||||
|
@ -82,7 +85,7 @@ func TestUserParam(t *testing.T) {
|
|||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Me", func(t *testing.T) {
|
||||
t.Run("me", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db, rw, r := setup(t)
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
|||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
|
@ -47,6 +47,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
|
@ -55,6 +56,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
|||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
workspace, err := db.InsertWorkspace(context.Background(), database.InsertWorkspaceParams{
|
||||
ID: uuid.New(),
|
||||
ProjectID: uuid.New(),
|
||||
|
@ -64,7 +66,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
ctx := chi.NewRouteContext()
|
||||
ctx.URLParams.Add("user", userID)
|
||||
ctx.URLParams.Add("user", userID.String())
|
||||
ctx.URLParams.Add("workspace", workspace.Name)
|
||||
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, ctx))
|
||||
return r, workspace
|
||||
|
|
|
@ -32,8 +32,8 @@ func TestWorkspaceParam(t *testing.T) {
|
|||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
|
@ -47,6 +47,7 @@ func TestWorkspaceParam(t *testing.T) {
|
|||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
|
@ -105,7 +106,7 @@ func TestWorkspaceParam(t *testing.T) {
|
|||
r, _ := setup(db)
|
||||
workspace, err := db.InsertWorkspace(context.Background(), database.InsertWorkspaceParams{
|
||||
ID: uuid.New(),
|
||||
OwnerID: "not-me",
|
||||
OwnerID: uuid.New(),
|
||||
Name: "hello",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -91,7 +91,7 @@ func (api *api) postProjectVersionsByOrganization(rw http.ResponseWriter, r *htt
|
|||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
Scope: database.ParameterScopeImportJob,
|
||||
ScopeID: jobID.String(),
|
||||
ScopeID: jobID,
|
||||
SourceScheme: parameterValue.SourceScheme,
|
||||
SourceValue: parameterValue.SourceValue,
|
||||
DestinationScheme: parameterValue.DestinationScheme,
|
||||
|
@ -200,10 +200,11 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
|||
|
||||
var project codersdk.Project
|
||||
err = api.Database.InTx(func(db database.Store) error {
|
||||
now := database.Now()
|
||||
dbProject, err := db.InsertProject(r.Context(), database.InsertProjectParams{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
OrganizationID: organization.ID,
|
||||
Name: createProject.Name,
|
||||
Provisioner: importJob.Provisioner,
|
||||
|
@ -212,6 +213,7 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
|||
if err != nil {
|
||||
return xerrors.Errorf("insert project: %s", err)
|
||||
}
|
||||
|
||||
err = db.UpdateProjectVersionByID(r.Context(), database.UpdateProjectVersionByIDParams{
|
||||
ID: projectVersion.ID,
|
||||
ProjectID: uuid.NullUUID{
|
||||
|
@ -222,6 +224,7 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
|||
if err != nil {
|
||||
return xerrors.Errorf("insert project version: %s", err)
|
||||
}
|
||||
|
||||
for _, parameterValue := range createProject.ParameterValues {
|
||||
_, err = db.InsertParameterValue(r.Context(), database.InsertParameterValueParams{
|
||||
ID: uuid.New(),
|
||||
|
@ -229,7 +232,7 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
|||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
Scope: database.ParameterScopeProject,
|
||||
ScopeID: dbProject.ID.String(),
|
||||
ScopeID: dbProject.ID,
|
||||
SourceScheme: parameterValue.SourceScheme,
|
||||
SourceValue: parameterValue.SourceValue,
|
||||
DestinationScheme: parameterValue.DestinationScheme,
|
||||
|
@ -238,6 +241,7 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
|||
return xerrors.Errorf("insert parameter value: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
project = convertProject(dbProject, 0)
|
||||
return nil
|
||||
})
|
||||
|
@ -291,18 +295,20 @@ func (api *api) projectByOrganizationAndName(rw http.ResponseWriter, r *http.Req
|
|||
OrganizationID: organization.ID,
|
||||
Name: projectName,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("no project found by name %q in the %q organization", projectName, organization.Name),
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("no project found by name %q in the %q organization", projectName, organization.Name),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project by organization and name: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByProjectIDs(r.Context(), []uuid.UUID{project.ID})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
|
@ -313,10 +319,12 @@ func (api *api) projectByOrganizationAndName(rw http.ResponseWriter, r *http.Req
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
count := uint32(0)
|
||||
if len(workspaceCounts) > 0 {
|
||||
count = uint32(workspaceCounts[0].Count)
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertProject(project, count))
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ func TestProvisionerDaemonsByOrganization(t *testing.T) {
|
|||
t.Run("NoAuth", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_, err := client.ProvisionerDaemonsByOrganization(context.Background(), "someorg")
|
||||
_, err := client.ProvisionerDaemonsByOrganization(context.Background(), uuid.New())
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
// ComputeScope targets identifiers to pull parameters from.
|
||||
type ComputeScope struct {
|
||||
ProjectImportJobID uuid.UUID
|
||||
OrganizationID string
|
||||
UserID string
|
||||
OrganizationID uuid.UUID
|
||||
UserID uuid.UUID
|
||||
ProjectID uuid.NullUUID
|
||||
WorkspaceID uuid.NullUUID
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func Compute(ctx context.Context, db database.Store, scope ComputeScope, options
|
|||
// Job parameters come second!
|
||||
err = compute.injectScope(ctx, database.GetParameterValuesByScopeParams{
|
||||
Scope: database.ParameterScopeImportJob,
|
||||
ScopeID: scope.ProjectImportJobID.String(),
|
||||
ScopeID: scope.ProjectImportJobID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -101,7 +101,7 @@ func Compute(ctx context.Context, db database.Store, scope ComputeScope, options
|
|||
DestinationScheme: parameterSchema.DefaultDestinationScheme,
|
||||
SourceValue: parameterSchema.DefaultSourceValue,
|
||||
Scope: database.ParameterScopeImportJob,
|
||||
ScopeID: scope.ProjectImportJobID.String(),
|
||||
ScopeID: scope.ProjectImportJobID,
|
||||
}, true)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("insert default value: %w", err)
|
||||
|
@ -115,7 +115,7 @@ func Compute(ctx context.Context, db database.Store, scope ComputeScope, options
|
|||
// Project parameters come third!
|
||||
err = compute.injectScope(ctx, database.GetParameterValuesByScopeParams{
|
||||
Scope: database.ParameterScopeProject,
|
||||
ScopeID: scope.ProjectID.UUID.String(),
|
||||
ScopeID: scope.ProjectID.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -135,7 +135,7 @@ func Compute(ctx context.Context, db database.Store, scope ComputeScope, options
|
|||
// Workspace parameters come last!
|
||||
err = compute.injectScope(ctx, database.GetParameterValuesByScopeParams{
|
||||
Scope: database.ParameterScopeWorkspace,
|
||||
ScopeID: scope.WorkspaceID.UUID.String(),
|
||||
ScopeID: scope.WorkspaceID.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestCompute(t *testing.T) {
|
|||
generateScope := func() parameter.ComputeScope {
|
||||
return parameter.ComputeScope{
|
||||
ProjectImportJobID: uuid.New(),
|
||||
OrganizationID: uuid.NewString(),
|
||||
OrganizationID: uuid.New(),
|
||||
ProjectID: uuid.NullUUID{
|
||||
UUID: uuid.New(),
|
||||
Valid: true,
|
||||
|
@ -27,7 +27,7 @@ func TestCompute(t *testing.T) {
|
|||
UUID: uuid.New(),
|
||||
Valid: true,
|
||||
},
|
||||
UserID: uuid.NewString(),
|
||||
UserID: uuid.New(),
|
||||
}
|
||||
}
|
||||
type parameterOptions struct {
|
||||
|
@ -88,7 +88,7 @@ func TestCompute(t *testing.T) {
|
|||
computedValue := computed[0]
|
||||
require.True(t, computedValue.DefaultSourceValue)
|
||||
require.Equal(t, database.ParameterScopeImportJob, computedValue.Scope)
|
||||
require.Equal(t, scope.ProjectImportJobID.String(), computedValue.ScopeID)
|
||||
require.Equal(t, scope.ProjectImportJobID, computedValue.ScopeID)
|
||||
require.Equal(t, computedValue.SourceValue, parameterSchema.DefaultSourceValue)
|
||||
})
|
||||
|
||||
|
@ -114,7 +114,7 @@ func TestCompute(t *testing.T) {
|
|||
ID: uuid.New(),
|
||||
Name: parameterSchema.Name,
|
||||
Scope: database.ParameterScopeImportJob,
|
||||
ScopeID: scope.ProjectImportJobID.String(),
|
||||
ScopeID: scope.ProjectImportJobID,
|
||||
SourceScheme: database.ParameterSourceSchemeData,
|
||||
SourceValue: "secondnop",
|
||||
DestinationScheme: database.ParameterDestinationSchemeEnvironmentVariable,
|
||||
|
@ -139,7 +139,7 @@ func TestCompute(t *testing.T) {
|
|||
ID: uuid.New(),
|
||||
Name: parameterSchema.Name,
|
||||
Scope: database.ParameterScopeProject,
|
||||
ScopeID: scope.ProjectID.UUID.String(),
|
||||
ScopeID: scope.ProjectID.UUID,
|
||||
SourceScheme: database.ParameterSourceSchemeData,
|
||||
SourceValue: "nop",
|
||||
DestinationScheme: database.ParameterDestinationSchemeEnvironmentVariable,
|
||||
|
@ -160,11 +160,12 @@ func TestCompute(t *testing.T) {
|
|||
parameterSchema := generateParameter(t, db, parameterOptions{
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
})
|
||||
|
||||
_, err := db.InsertParameterValue(context.Background(), database.InsertParameterValueParams{
|
||||
ID: uuid.New(),
|
||||
Name: parameterSchema.Name,
|
||||
Scope: database.ParameterScopeWorkspace,
|
||||
ScopeID: scope.WorkspaceID.UUID.String(),
|
||||
ScopeID: scope.WorkspaceID.UUID,
|
||||
SourceScheme: database.ParameterSourceSchemeData,
|
||||
SourceValue: "nop",
|
||||
DestinationScheme: database.ParameterDestinationSchemeEnvironmentVariable,
|
||||
|
@ -189,7 +190,7 @@ func TestCompute(t *testing.T) {
|
|||
ID: uuid.New(),
|
||||
Name: parameterSchema.Name,
|
||||
Scope: database.ParameterScopeWorkspace,
|
||||
ScopeID: scope.WorkspaceID.UUID.String(),
|
||||
ScopeID: scope.WorkspaceID.UUID,
|
||||
SourceScheme: database.ParameterSourceSchemeData,
|
||||
SourceValue: "nop",
|
||||
DestinationScheme: database.ParameterDestinationSchemeEnvironmentVariable,
|
||||
|
|
|
@ -138,7 +138,7 @@ func convertParameterValue(parameterValue database.ParameterValue) codersdk.Para
|
|||
}
|
||||
}
|
||||
|
||||
func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.ParameterScope, string, bool) {
|
||||
func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.ParameterScope, uuid.UUID, bool) {
|
||||
var scope database.ParameterScope
|
||||
switch chi.URLParam(r, "scope") {
|
||||
case string(codersdk.ParameterOrganization):
|
||||
|
@ -153,8 +153,17 @@ func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.Parameter
|
|||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: fmt.Sprintf("invalid scope %q", scope),
|
||||
})
|
||||
return scope, "", false
|
||||
return scope, uuid.Nil, false
|
||||
}
|
||||
|
||||
return scope, chi.URLParam(r, "id"), true
|
||||
id := chi.URLParam(r, "id")
|
||||
uid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: fmt.Sprintf("invalid uuid %q: %s", id, err),
|
||||
})
|
||||
return scope, uuid.Nil, false
|
||||
}
|
||||
|
||||
return scope, uid, true
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ func TestDeleteProject(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
err := client.DeleteProject(context.Background(), project.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/provisioner/echo"
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
)
|
||||
|
@ -37,7 +38,7 @@ func TestProvisionerJobLogs(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
before := time.Now().UTC()
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
|
@ -75,7 +76,7 @@ func TestProvisionerJobLogs(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
before := database.Now()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancelFunc)
|
||||
|
@ -111,7 +112,7 @@ func TestProvisionerJobLogs(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
logs, err := client.WorkspaceBuildLogsBefore(context.Background(), workspace.LatestBuild.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -32,12 +32,14 @@ func (api *api) firstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
if userCount == 0 {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: "The initial user has not been created!",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusOK, httpapi.Response{
|
||||
Message: "The initial user has already been created!",
|
||||
})
|
||||
|
@ -49,6 +51,7 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
if !httpapi.Read(rw, r, &createUser) {
|
||||
return
|
||||
}
|
||||
|
||||
// This should only function for the first user.
|
||||
userCount, err := api.Database.GetUserCount(r.Context())
|
||||
if err != nil {
|
||||
|
@ -57,6 +60,7 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
// If a user already exists, the initial admin user no longer can be created.
|
||||
if userCount != 0 {
|
||||
httpapi.Write(rw, http.StatusConflict, httpapi.Response{
|
||||
|
@ -64,6 +68,7 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
hashedPassword, err := userpassword.Hash(createUser.Password)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
|
@ -77,7 +82,7 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
var organization database.Organization
|
||||
err = api.Database.InTx(func(s database.Store) error {
|
||||
user, err = api.Database.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Email: createUser.Email,
|
||||
HashedPassword: []byte(hashedPassword),
|
||||
Username: createUser.Username,
|
||||
|
@ -89,8 +94,8 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
return xerrors.Errorf("create user: %w", err)
|
||||
}
|
||||
organization, err = api.Database.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: uuid.NewString(),
|
||||
Name: createUser.Organization,
|
||||
ID: uuid.New(),
|
||||
Name: createUser.OrganizationName,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
|
@ -190,7 +195,7 @@ func (api *api) postUsers(rw http.ResponseWriter, r *http.Request) {
|
|||
var user database.User
|
||||
err = api.Database.InTx(func(db database.Store) error {
|
||||
user, err = db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Email: createUser.Email,
|
||||
HashedPassword: []byte(hashedPassword),
|
||||
Username: createUser.Username,
|
||||
|
@ -317,7 +322,7 @@ func (api *api) postOrganizationsByUser(rw http.ResponseWriter, r *http.Request)
|
|||
var organization database.Organization
|
||||
err = api.Database.InTx(func(db database.Store) error {
|
||||
organization, err = api.Database.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Name: req.Name,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
|
@ -611,7 +616,7 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
|||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
Scope: database.ParameterScopeWorkspace,
|
||||
ScopeID: workspace.ID.String(),
|
||||
ScopeID: workspace.ID,
|
||||
SourceScheme: parameterValue.SourceScheme,
|
||||
SourceValue: parameterValue.SourceValue,
|
||||
DestinationScheme: parameterValue.DestinationScheme,
|
||||
|
@ -649,7 +654,7 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
|||
WorkspaceID: workspace.ID,
|
||||
ProjectVersionID: projectVersion.ID,
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
Initiator: apiKey.UserID,
|
||||
InitiatorID: apiKey.UserID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
JobID: provisionerJob.ID,
|
||||
})
|
||||
|
@ -725,35 +730,35 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
buildByWorkspaceID := map[string]database.WorkspaceBuild{}
|
||||
buildByWorkspaceID := map[uuid.UUID]database.WorkspaceBuild{}
|
||||
for _, workspaceBuild := range workspaceBuilds {
|
||||
buildByWorkspaceID[workspaceBuild.WorkspaceID.String()] = workspaceBuild
|
||||
buildByWorkspaceID[workspaceBuild.WorkspaceID] = workspaceBuild
|
||||
}
|
||||
projectByID := map[string]database.Project{}
|
||||
projectByID := map[uuid.UUID]database.Project{}
|
||||
for _, project := range projects {
|
||||
projectByID[project.ID.String()] = project
|
||||
projectByID[project.ID] = project
|
||||
}
|
||||
jobByID := map[string]database.ProvisionerJob{}
|
||||
jobByID := map[uuid.UUID]database.ProvisionerJob{}
|
||||
for _, job := range jobs {
|
||||
jobByID[job.ID.String()] = job
|
||||
jobByID[job.ID] = job
|
||||
}
|
||||
apiWorkspaces := make([]codersdk.Workspace, 0, len(workspaces))
|
||||
for _, workspace := range workspaces {
|
||||
build, exists := buildByWorkspaceID[workspace.ID.String()]
|
||||
build, exists := buildByWorkspaceID[workspace.ID]
|
||||
if !exists {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("build not found for workspace %q", workspace.Name),
|
||||
})
|
||||
return
|
||||
}
|
||||
project, exists := projectByID[workspace.ProjectID.String()]
|
||||
project, exists := projectByID[workspace.ProjectID]
|
||||
if !exists {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("project not found for workspace %q", workspace.Name),
|
||||
})
|
||||
return
|
||||
}
|
||||
job, exists := jobByID[build.JobID.String()]
|
||||
job, exists := jobByID[build.JobID]
|
||||
if !exists {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("build job not found for workspace %q", workspace.Name),
|
||||
|
|
|
@ -27,10 +27,10 @@ func TestFirstUser(t *testing.T) {
|
|||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateFirstUser(context.Background(), codersdk.CreateFirstUserRequest{
|
||||
Email: "some@email.com",
|
||||
Username: "exampleuser",
|
||||
Password: "password",
|
||||
Organization: "someorg",
|
||||
Email: "some@email.com",
|
||||
Username: "exampleuser",
|
||||
Password: "password",
|
||||
OrganizationName: "someorg",
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -62,10 +62,10 @@ func TestPostLogin(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
req := codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Organization: "testorg",
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
OrganizationName: "testorg",
|
||||
}
|
||||
_, err := client.CreateFirstUser(context.Background(), req)
|
||||
require.NoError(t, err)
|
||||
|
@ -82,10 +82,10 @@ func TestPostLogin(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
req := codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Organization: "testorg",
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
OrganizationName: "testorg",
|
||||
}
|
||||
_, err := client.CreateFirstUser(context.Background(), req)
|
||||
require.NoError(t, err)
|
||||
|
@ -137,13 +137,13 @@ func TestPostUsers(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
me, err := client.User(context.Background(), "")
|
||||
me, err := client.User(context.Background(), codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
_, err = client.CreateUser(context.Background(), codersdk.CreateUserRequest{
|
||||
Email: me.Email,
|
||||
Username: me.Username,
|
||||
Password: "password",
|
||||
OrganizationID: "someorg",
|
||||
OrganizationID: uuid.New(),
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -155,7 +155,7 @@ func TestPostUsers(t *testing.T) {
|
|||
client := coderdtest.New(t, nil)
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateUser(context.Background(), codersdk.CreateUserRequest{
|
||||
OrganizationID: "not-exists",
|
||||
OrganizationID: uuid.New(),
|
||||
Email: "another@user.org",
|
||||
Username: "someone-else",
|
||||
Password: "testing",
|
||||
|
@ -170,7 +170,7 @@ func TestPostUsers(t *testing.T) {
|
|||
client := coderdtest.New(t, nil)
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
|
||||
org, err := other.CreateOrganization(context.Background(), "", codersdk.CreateOrganizationRequest{
|
||||
org, err := other.CreateOrganization(context.Background(), codersdk.Me, codersdk.CreateOrganizationRequest{
|
||||
Name: "another",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -204,7 +204,7 @@ func TestUserByName(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.User(context.Background(), "")
|
||||
_, err := client.User(context.Background(), codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ func TestOrganizationsByUser(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
orgs, err := client.OrganizationsByUser(context.Background(), "")
|
||||
orgs, err := client.OrganizationsByUser(context.Background(), codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, orgs)
|
||||
require.Len(t, orgs, 1)
|
||||
|
@ -224,7 +224,7 @@ func TestOrganizationByUserAndName(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.OrganizationByName(context.Background(), "", "nothing")
|
||||
_, err := client.OrganizationByName(context.Background(), codersdk.Me, "nothing")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
|
@ -235,11 +235,11 @@ func TestOrganizationByUserAndName(t *testing.T) {
|
|||
client := coderdtest.New(t, nil)
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
|
||||
org, err := other.CreateOrganization(context.Background(), "", codersdk.CreateOrganizationRequest{
|
||||
org, err := other.CreateOrganization(context.Background(), codersdk.Me, codersdk.CreateOrganizationRequest{
|
||||
Name: "another",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = client.OrganizationByName(context.Background(), "", org.Name)
|
||||
_, err = client.OrganizationByName(context.Background(), codersdk.Me, org.Name)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
|
||||
|
@ -251,7 +251,7 @@ func TestOrganizationByUserAndName(t *testing.T) {
|
|||
user := coderdtest.CreateFirstUser(t, client)
|
||||
org, err := client.Organization(context.Background(), user.OrganizationID)
|
||||
require.NoError(t, err)
|
||||
_, err = client.OrganizationByName(context.Background(), "", org.Name)
|
||||
_, err = client.OrganizationByName(context.Background(), codersdk.Me, org.Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ func TestPostOrganizationsByUser(t *testing.T) {
|
|||
user := coderdtest.CreateFirstUser(t, client)
|
||||
org, err := client.Organization(context.Background(), user.OrganizationID)
|
||||
require.NoError(t, err)
|
||||
_, err = client.CreateOrganization(context.Background(), "", codersdk.CreateOrganizationRequest{
|
||||
_, err = client.CreateOrganization(context.Background(), codersdk.Me, codersdk.CreateOrganizationRequest{
|
||||
Name: org.Name,
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
|
@ -276,7 +276,7 @@ func TestPostOrganizationsByUser(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateOrganization(context.Background(), "", codersdk.CreateOrganizationRequest{
|
||||
_, err := client.CreateOrganization(context.Background(), codersdk.Me, codersdk.CreateOrganizationRequest{
|
||||
Name: "new",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -291,7 +291,7 @@ func TestPostAPIKey(t *testing.T) {
|
|||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
client.SessionToken = ""
|
||||
_, err := client.CreateAPIKey(context.Background(), "")
|
||||
_, err := client.CreateAPIKey(context.Background(), codersdk.Me)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
|
||||
|
@ -301,7 +301,7 @@ func TestPostAPIKey(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
apiKey, err := client.CreateAPIKey(context.Background(), "")
|
||||
apiKey, err := client.CreateAPIKey(context.Background(), codersdk.Me)
|
||||
require.NotNil(t, apiKey)
|
||||
require.GreaterOrEqual(t, len(apiKey.Key), 2)
|
||||
require.NoError(t, err)
|
||||
|
@ -314,7 +314,7 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateWorkspace(context.Background(), "", codersdk.CreateWorkspaceRequest{
|
||||
_, err := client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: uuid.New(),
|
||||
Name: "workspace",
|
||||
})
|
||||
|
@ -330,14 +330,14 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
|||
first := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
other := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
|
||||
org, err := other.CreateOrganization(context.Background(), "", codersdk.CreateOrganizationRequest{
|
||||
org, err := other.CreateOrganization(context.Background(), codersdk.Me, codersdk.CreateOrganizationRequest{
|
||||
Name: "another",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
version := coderdtest.CreateProjectVersion(t, other, org.ID, nil)
|
||||
project := coderdtest.CreateProject(t, other, org.ID, version.ID)
|
||||
|
||||
_, err = client.CreateWorkspace(context.Background(), "", codersdk.CreateWorkspaceRequest{
|
||||
_, err = client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: "workspace",
|
||||
})
|
||||
|
@ -355,8 +355,8 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
_, err := client.CreateWorkspace(context.Background(), "", codersdk.CreateWorkspaceRequest{
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: workspace.Name,
|
||||
})
|
||||
|
@ -374,7 +374,7 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
_ = coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
_ = coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ func TestWorkspacesByUser(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.WorkspacesByUser(context.Background(), "")
|
||||
_, err := client.WorkspacesByUser(context.Background(), codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("List", func(t *testing.T) {
|
||||
|
@ -395,8 +395,8 @@ func TestWorkspacesByUser(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
_ = coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspaces, err := client.WorkspacesByUser(context.Background(), "")
|
||||
_ = coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
workspaces, err := client.WorkspacesByUser(context.Background(), codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspaces, 1)
|
||||
})
|
||||
|
@ -408,7 +408,7 @@ func TestWorkspaceByUserAndName(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.WorkspaceByName(context.Background(), "", "something")
|
||||
_, err := client.WorkspaceByName(context.Background(), codersdk.Me, "something")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
|
@ -421,8 +421,8 @@ func TestWorkspaceByUserAndName(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
_, err := client.WorkspaceByName(context.Background(), "", workspace.Name)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.WorkspaceByName(context.Background(), codersdk.Me, workspace.Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ func convertWorkspaceBuild(workspaceBuild database.WorkspaceBuild, job codersdk.
|
|||
AfterID: workspaceBuild.AfterID.UUID,
|
||||
Name: workspaceBuild.Name,
|
||||
Transition: workspaceBuild.Transition,
|
||||
Initiator: workspaceBuild.Initiator,
|
||||
InitiatorID: workspaceBuild.InitiatorID,
|
||||
Job: job,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func TestWorkspaceBuild(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.WorkspaceBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) {
|
|||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
var build codersdk.WorkspaceBuild
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
|
@ -72,7 +72,7 @@ func TestWorkspaceBuildResources(t *testing.T) {
|
|||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
closeDaemon.Close()
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -105,7 +105,7 @@ func TestWorkspaceBuildResources(t *testing.T) {
|
|||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
|
@ -152,7 +152,7 @@ func TestWorkspaceBuildLogs(t *testing.T) {
|
|||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancelFunc)
|
||||
logs, err := client.WorkspaceBuildLogsAfter(ctx, workspace.LatestBuild.ID, before)
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestPostWorkspaceAuthAWSInstanceIdentity(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
client.HTTPClient = metadataClient
|
||||
|
@ -110,7 +110,7 @@ func TestPostWorkspaceAuthGoogleInstanceIdentity(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
_, err := client.AuthWorkspaceGoogleInstanceIdentity(context.Background(), "", metadata)
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestWorkspaceResource(t *testing.T) {
|
|||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
|
@ -81,7 +81,7 @@ func TestWorkspaceAgentListen(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
daemonCloser.Close()
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
|||
BeforeID: priorHistoryID,
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
ProvisionerState: priorHistory.ProvisionerState,
|
||||
Initiator: apiKey.UserID,
|
||||
InitiatorID: apiKey.UserID,
|
||||
Transition: createBuild.Transition,
|
||||
JobID: provisionerJob.ID,
|
||||
})
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestWorkspace(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.Workspace(context.Background(), workspace.ID)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ func TestWorkspaceBuilds(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.WorkspaceBuilds(context.Background(), workspace.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
@ -54,7 +54,7 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
ProjectVersionID: uuid.New(),
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
|
@ -75,7 +75,7 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
|||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
_, err := client.CreateWorkspace(context.Background(), "", codersdk.CreateWorkspaceRequest{
|
||||
_, err := client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: "workspace",
|
||||
})
|
||||
|
@ -94,7 +94,7 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
|||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
// Close here so workspace build doesn't process!
|
||||
closeDaemon.Close()
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
ProjectVersionID: project.ActiveVersionID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
|
@ -113,7 +113,7 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
build, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
ProjectVersionID: project.ActiveVersionID,
|
||||
|
@ -135,7 +135,7 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
build, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
Transition: database.WorkspaceTransitionDelete,
|
||||
|
@ -160,7 +160,7 @@ func TestWorkspaceBuildByName(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
_, err := client.WorkspaceBuildByName(context.Background(), workspace.ID, "something")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -175,7 +175,7 @@ func TestWorkspaceBuildByName(t *testing.T) {
|
|||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, "me", project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
build, err := client.WorkspaceBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
_, err = client.WorkspaceBuildByName(context.Background(), workspace.ID, build.Name)
|
||||
|
|
|
@ -8,13 +8,14 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
)
|
||||
|
||||
// Organization is the JSON representation of a Coder organization.
|
||||
type Organization struct {
|
||||
ID string `json:"id" validate:"required"`
|
||||
ID uuid.UUID `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
CreatedAt time.Time `json:"created_at" validate:"required"`
|
||||
UpdatedAt time.Time `json:"updated_at" validate:"required"`
|
||||
|
@ -47,86 +48,113 @@ type CreateProjectRequest struct {
|
|||
ParameterValues []CreateParameterRequest `json:"parameter_values"`
|
||||
}
|
||||
|
||||
func (c *Client) Organization(ctx context.Context, id string) (Organization, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s", id), nil)
|
||||
func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s", id.String()), nil)
|
||||
if err != nil {
|
||||
return Organization{}, err
|
||||
return Organization{}, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return Organization{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var organization Organization
|
||||
return organization, json.NewDecoder(res.Body).Decode(&organization)
|
||||
}
|
||||
|
||||
// ProvisionerDaemonsByOrganization returns provisioner daemons available for an organization.
|
||||
func (c *Client) ProvisionerDaemonsByOrganization(ctx context.Context, organization string) ([]ProvisionerDaemon, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/provisionerdaemons", organization), nil)
|
||||
func (c *Client) ProvisionerDaemonsByOrganization(ctx context.Context, organizationID uuid.UUID) ([]ProvisionerDaemon, error) {
|
||||
res, err := c.request(ctx, http.MethodGet,
|
||||
fmt.Sprintf("/api/v2/organizations/%s/provisionerdaemons", organizationID.String()),
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var daemons []ProvisionerDaemon
|
||||
return daemons, json.NewDecoder(res.Body).Decode(&daemons)
|
||||
}
|
||||
|
||||
// CreateProjectVersion processes source-code and optionally associates the version with a project.
|
||||
// Executing without a project is useful for validating source-code.
|
||||
func (c *Client) CreateProjectVersion(ctx context.Context, organization string, req CreateProjectVersionRequest) (ProjectVersion, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/organizations/%s/projectversions", organization), req)
|
||||
func (c *Client) CreateProjectVersion(ctx context.Context, organizationID uuid.UUID, req CreateProjectVersionRequest) (ProjectVersion, error) {
|
||||
res, err := c.request(ctx, http.MethodPost,
|
||||
fmt.Sprintf("/api/v2/organizations/%s/projectversions", organizationID.String()),
|
||||
req,
|
||||
)
|
||||
if err != nil {
|
||||
return ProjectVersion{}, err
|
||||
return ProjectVersion{}, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return ProjectVersion{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var projectVersion ProjectVersion
|
||||
return projectVersion, json.NewDecoder(res.Body).Decode(&projectVersion)
|
||||
}
|
||||
|
||||
// CreateProject creates a new project inside an organization.
|
||||
func (c *Client) CreateProject(ctx context.Context, organization string, request CreateProjectRequest) (Project, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/organizations/%s/projects", organization), request)
|
||||
func (c *Client) CreateProject(ctx context.Context, organizationID uuid.UUID, request CreateProjectRequest) (Project, error) {
|
||||
res, err := c.request(ctx, http.MethodPost,
|
||||
fmt.Sprintf("/api/v2/organizations/%s/projects", organizationID.String()),
|
||||
request,
|
||||
)
|
||||
if err != nil {
|
||||
return Project{}, err
|
||||
return Project{}, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return Project{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var project Project
|
||||
return project, json.NewDecoder(res.Body).Decode(&project)
|
||||
}
|
||||
|
||||
// ProjectsByOrganization lists all projects inside of an organization.
|
||||
func (c *Client) ProjectsByOrganization(ctx context.Context, organization string) ([]Project, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/projects", organization), nil)
|
||||
func (c *Client) ProjectsByOrganization(ctx context.Context, organizationID uuid.UUID) ([]Project, error) {
|
||||
res, err := c.request(ctx, http.MethodGet,
|
||||
fmt.Sprintf("/api/v2/organizations/%s/projects", organizationID.String()),
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var projects []Project
|
||||
return projects, json.NewDecoder(res.Body).Decode(&projects)
|
||||
}
|
||||
|
||||
// ProjectByName finds a project inside the organization provided with a case-insensitive name.
|
||||
func (c *Client) ProjectByName(ctx context.Context, organization, name string) (Project, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/projects/%s", organization, name), nil)
|
||||
func (c *Client) ProjectByName(ctx context.Context, organizationID uuid.UUID, name string) (Project, error) {
|
||||
res, err := c.request(ctx, http.MethodGet,
|
||||
fmt.Sprintf("/api/v2/organizations/%s/projects/%s", organizationID.String(), name),
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return Project{}, err
|
||||
return Project{}, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return Project{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var project Project
|
||||
return project, json.NewDecoder(res.Body).Decode(&project)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
|
@ -27,7 +28,7 @@ type Parameter struct {
|
|||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Scope ParameterScope `db:"scope" json:"scope"`
|
||||
ScopeID string `db:"scope_id" json:"scope_id"`
|
||||
ScopeID uuid.UUID `db:"scope_id" json:"scope_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
SourceScheme database.ParameterSourceScheme `db:"source_scheme" json:"source_scheme"`
|
||||
DestinationScheme database.ParameterDestinationScheme `db:"destination_scheme" json:"destination_scheme"`
|
||||
|
@ -41,40 +42,47 @@ type CreateParameterRequest struct {
|
|||
DestinationScheme database.ParameterDestinationScheme `json:"destination_scheme" validate:"oneof=environment_variable provisioner_variable,required"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateParameter(ctx context.Context, scope ParameterScope, id string, req CreateParameterRequest) (Parameter, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id), req)
|
||||
func (c *Client) CreateParameter(ctx context.Context, scope ParameterScope, id uuid.UUID, req CreateParameterRequest) (Parameter, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id.String()), req)
|
||||
if err != nil {
|
||||
return Parameter{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return Parameter{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var param Parameter
|
||||
return param, json.NewDecoder(res.Body).Decode(¶m)
|
||||
}
|
||||
|
||||
func (c *Client) DeleteParameter(ctx context.Context, scope ParameterScope, id, name string) error {
|
||||
res, err := c.request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/parameters/%s/%s/%s", scope, id, name), nil)
|
||||
func (c *Client) DeleteParameter(ctx context.Context, scope ParameterScope, id uuid.UUID, name string) error {
|
||||
res, err := c.request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/parameters/%s/%s/%s", scope, id.String(), name), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return readBodyAsError(res)
|
||||
}
|
||||
|
||||
_, _ = io.Copy(io.Discard, res.Body)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Parameters(ctx context.Context, scope ParameterScope, id string) ([]Parameter, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id), nil)
|
||||
func (c *Client) Parameters(ctx context.Context, scope ParameterScope, id uuid.UUID) ([]Parameter, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/parameters/%s/%s", scope, id.String()), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var parameters []Parameter
|
||||
return parameters, json.NewDecoder(res.Body).Decode(¶meters)
|
||||
}
|
||||
|
|
|
@ -12,14 +12,13 @@ import (
|
|||
"github.com/coder/coder/coderd/database"
|
||||
)
|
||||
|
||||
// Project is the JSON representation of a Coder project.
|
||||
// This type matches the database object for now, but is
|
||||
// abstracted for ease of change later on.
|
||||
// Project is the JSON representation of a Coder project. This type matches the
|
||||
// database object for now, but is abstracted for ease of change later on.
|
||||
type Project struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
OrganizationID string `json:"organization_id"`
|
||||
OrganizationID uuid.UUID `json:"organization_id"`
|
||||
Name string `json:"name"`
|
||||
Provisioner database.ProvisionerType `json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `json:"active_version_id"`
|
||||
|
|
|
@ -10,32 +10,35 @@ import (
|
|||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Me is used as a replacement for your own ID.
|
||||
var Me = uuid.Nil
|
||||
|
||||
// User represents a user in Coder.
|
||||
type User struct {
|
||||
ID string `json:"id" validate:"required"`
|
||||
ID uuid.UUID `json:"id" validate:"required"`
|
||||
Email string `json:"email" validate:"required"`
|
||||
CreatedAt time.Time `json:"created_at" validate:"required"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateFirstUserRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required,username"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Organization string `json:"organization" validate:"required,username"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required,username"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
OrganizationName string `json:"organization" validate:"required,username"`
|
||||
}
|
||||
|
||||
// CreateFirstUserResponse contains IDs for newly created user info.
|
||||
type CreateFirstUserResponse struct {
|
||||
UserID string `json:"user_id"`
|
||||
OrganizationID string `json:"organization_id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
OrganizationID uuid.UUID `json:"organization_id"`
|
||||
}
|
||||
|
||||
type CreateUserRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required,username"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
OrganizationID string `json:"organization_id" validate:"required"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required,username"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
OrganizationID uuid.UUID `json:"organization_id" validate:"required"`
|
||||
}
|
||||
|
||||
// LoginWithPasswordRequest enables callers to authenticate with email and password.
|
||||
|
@ -113,11 +116,8 @@ func (c *Client) CreateUser(ctx context.Context, req CreateUserRequest) (User, e
|
|||
}
|
||||
|
||||
// CreateAPIKey generates an API key for the user ID provided.
|
||||
func (c *Client) CreateAPIKey(ctx context.Context, id string) (*GenerateAPIKeyResponse, error) {
|
||||
if id == "" {
|
||||
id = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", id), nil)
|
||||
func (c *Client) CreateAPIKey(ctx context.Context, userID uuid.UUID) (*GenerateAPIKeyResponse, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", uuidOrMe(userID)), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -162,12 +162,9 @@ func (c *Client) Logout(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// User returns a user for the ID provided.
|
||||
// If the ID string is empty, the current user will be returned.
|
||||
func (c *Client) User(ctx context.Context, id string) (User, error) {
|
||||
if id == "" {
|
||||
id = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", id), nil)
|
||||
// If the uuid is nil, the current user will be returned.
|
||||
func (c *Client) User(ctx context.Context, id uuid.UUID) (User, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", uuidOrMe(id)), nil)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
|
@ -180,11 +177,8 @@ func (c *Client) User(ctx context.Context, id string) (User, error) {
|
|||
}
|
||||
|
||||
// OrganizationsByUser returns all organizations the user is a member of.
|
||||
func (c *Client) OrganizationsByUser(ctx context.Context, id string) ([]Organization, error) {
|
||||
if id == "" {
|
||||
id = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", id), nil)
|
||||
func (c *Client) OrganizationsByUser(ctx context.Context, userID uuid.UUID) ([]Organization, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", uuidOrMe(userID)), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -196,11 +190,8 @@ func (c *Client) OrganizationsByUser(ctx context.Context, id string) ([]Organiza
|
|||
return orgs, json.NewDecoder(res.Body).Decode(&orgs)
|
||||
}
|
||||
|
||||
func (c *Client) OrganizationByName(ctx context.Context, user, name string) (Organization, error) {
|
||||
if user == "" {
|
||||
user = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", user, name), nil)
|
||||
func (c *Client) OrganizationByName(ctx context.Context, userID uuid.UUID, name string) (Organization, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", uuidOrMe(userID), name), nil)
|
||||
if err != nil {
|
||||
return Organization{}, err
|
||||
}
|
||||
|
@ -213,68 +204,74 @@ func (c *Client) OrganizationByName(ctx context.Context, user, name string) (Org
|
|||
}
|
||||
|
||||
// CreateOrganization creates an organization and adds the provided user as an admin.
|
||||
func (c *Client) CreateOrganization(ctx context.Context, user string, req CreateOrganizationRequest) (Organization, error) {
|
||||
if user == "" {
|
||||
user = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", user), req)
|
||||
func (c *Client) CreateOrganization(ctx context.Context, userID uuid.UUID, req CreateOrganizationRequest) (Organization, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", uuidOrMe(userID)), req)
|
||||
if err != nil {
|
||||
return Organization{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return Organization{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var org Organization
|
||||
return org, json.NewDecoder(res.Body).Decode(&org)
|
||||
}
|
||||
|
||||
// CreateWorkspace creates a new workspace for the project specified.
|
||||
func (c *Client) CreateWorkspace(ctx context.Context, user string, request CreateWorkspaceRequest) (Workspace, error) {
|
||||
if user == "" {
|
||||
user = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/workspaces", user), request)
|
||||
func (c *Client) CreateWorkspace(ctx context.Context, userID uuid.UUID, request CreateWorkspaceRequest) (Workspace, error) {
|
||||
res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/workspaces", uuidOrMe(userID)), request)
|
||||
if err != nil {
|
||||
return Workspace{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return Workspace{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var workspace Workspace
|
||||
return workspace, json.NewDecoder(res.Body).Decode(&workspace)
|
||||
}
|
||||
|
||||
// WorkspacesByUser returns all workspaces the specified user has access to.
|
||||
func (c *Client) WorkspacesByUser(ctx context.Context, user string) ([]Workspace, error) {
|
||||
if user == "" {
|
||||
user = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", user), nil)
|
||||
func (c *Client) WorkspacesByUser(ctx context.Context, userID uuid.UUID) ([]Workspace, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", uuidOrMe(userID)), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var workspaces []Workspace
|
||||
return workspaces, json.NewDecoder(res.Body).Decode(&workspaces)
|
||||
}
|
||||
|
||||
func (c *Client) WorkspaceByName(ctx context.Context, user, name string) (Workspace, error) {
|
||||
if user == "" {
|
||||
user = "me"
|
||||
}
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces/%s", user, name), nil)
|
||||
func (c *Client) WorkspaceByName(ctx context.Context, userID uuid.UUID, name string) (Workspace, error) {
|
||||
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces/%s", uuidOrMe(userID), name), nil)
|
||||
if err != nil {
|
||||
return Workspace{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return Workspace{}, readBodyAsError(res)
|
||||
}
|
||||
|
||||
var workspace Workspace
|
||||
return workspace, json.NewDecoder(res.Body).Decode(&workspace)
|
||||
}
|
||||
|
||||
// uuidOrMe returns the provided uuid as a string if it's valid, ortherwise
|
||||
// `me`.
|
||||
func uuidOrMe(id uuid.UUID) string {
|
||||
if id == Me {
|
||||
return "me"
|
||||
}
|
||||
|
||||
return id.String()
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ type WorkspaceBuild struct {
|
|||
AfterID uuid.UUID `json:"after_id"`
|
||||
Name string `json:"name"`
|
||||
Transition database.WorkspaceTransition `json:"transition"`
|
||||
Initiator string `json:"initiator"`
|
||||
InitiatorID uuid.UUID `json:"initiator_id"`
|
||||
Job ProvisionerJob `json:"job"`
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ type Workspace struct {
|
|||
ID uuid.UUID `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
OwnerID string `json:"owner_id"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
ProjectName string `json:"project_name"`
|
||||
LatestBuild WorkspaceBuild `json:"latest_build"`
|
||||
|
|
|
@ -38,6 +38,7 @@ func List() ([]Example, error) {
|
|||
returnError = xerrors.Errorf("read dir: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, dir := range dirs {
|
||||
exampleID := dir.Name()
|
||||
// Each one of these is a example!
|
||||
|
@ -46,31 +47,37 @@ func List() ([]Example, error) {
|
|||
returnError = xerrors.Errorf("example %q does not contain README.md", exampleID)
|
||||
return
|
||||
}
|
||||
|
||||
frontMatter, err := pageparser.ParseFrontMatterAndContent(bytes.NewReader(readme))
|
||||
if err != nil {
|
||||
returnError = xerrors.Errorf("parse example %q front matter: %w", exampleID, err)
|
||||
return
|
||||
}
|
||||
|
||||
nameRaw, exists := frontMatter.FrontMatter["name"]
|
||||
if !exists {
|
||||
returnError = xerrors.Errorf("example %q front matter does not contain name", exampleID)
|
||||
return
|
||||
}
|
||||
|
||||
name, valid := nameRaw.(string)
|
||||
if !valid {
|
||||
returnError = xerrors.Errorf("example %q name isn't a string", exampleID)
|
||||
return
|
||||
}
|
||||
|
||||
descriptionRaw, exists := frontMatter.FrontMatter["description"]
|
||||
if !exists {
|
||||
returnError = xerrors.Errorf("example %q front matter does not contain name", exampleID)
|
||||
return
|
||||
}
|
||||
|
||||
description, valid := descriptionRaw.(string)
|
||||
if !valid {
|
||||
returnError = xerrors.Errorf("example %q description isn't a string", exampleID)
|
||||
return
|
||||
}
|
||||
|
||||
examples = append(examples, Example{
|
||||
ID: exampleID,
|
||||
Name: name,
|
||||
|
@ -87,8 +94,9 @@ func Archive(exampleID string) ([]byte, error) {
|
|||
rawData, err, _ := archives.Do(exampleID, func() (interface{}, error) {
|
||||
examples, err := List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, xerrors.Errorf("list: %w", err)
|
||||
}
|
||||
|
||||
var selected Example
|
||||
for _, example := range examples {
|
||||
if example.ID != exampleID {
|
||||
|
@ -97,6 +105,7 @@ func Archive(exampleID string) ([]byte, error) {
|
|||
selected = example
|
||||
break
|
||||
}
|
||||
|
||||
if selected.ID == "" {
|
||||
return nil, xerrors.Errorf("example with id %q not found", exampleID)
|
||||
}
|
||||
|
@ -114,27 +123,33 @@ func Archive(exampleID string) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, xerrors.Errorf("open file: %w", err)
|
||||
}
|
||||
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("stat file: %w", err)
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
data := make([]byte, info.Size())
|
||||
_, err = file.Read(data)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("read data: %w", err)
|
||||
}
|
||||
|
||||
header, err := tar.FileInfoHeader(info, entry.Name())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get file header: %w", err)
|
||||
}
|
||||
header.Mode = 0644
|
||||
|
||||
err = tarWriter.WriteHeader(header)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("write file: %w", err)
|
||||
}
|
||||
|
||||
_, err = tarWriter.Write(data)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("write: %w", err)
|
||||
|
@ -144,6 +159,7 @@ func Archive(exampleID string) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, xerrors.Errorf("flush archive: %w", err)
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
})
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue