mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: Rename Projects to Templates (#880)
Customer feedback indicated projects was a confusing name.
After querying the team internally, it seemed unanimous
that it is indeed a confusing name.
Here's for a lil less confusion @ashmeer7 🥂
This commit is contained in:
+20
-20
@@ -76,11 +76,11 @@ func New(options *Options) (http.Handler, func()) {
|
||||
)
|
||||
r.Get("/", api.organization)
|
||||
r.Get("/provisionerdaemons", api.provisionerDaemonsByOrganization)
|
||||
r.Post("/projectversions", api.postProjectVersionsByOrganization)
|
||||
r.Route("/projects", func(r chi.Router) {
|
||||
r.Post("/", api.postProjectsByOrganization)
|
||||
r.Get("/", api.projectsByOrganization)
|
||||
r.Get("/{projectname}", api.projectByOrganizationAndName)
|
||||
r.Post("/templateversions", api.postTemplateVersionsByOrganization)
|
||||
r.Route("/templates", func(r chi.Router) {
|
||||
r.Post("/", api.postTemplatesByOrganization)
|
||||
r.Get("/", api.templatesByOrganization)
|
||||
r.Get("/{templatename}", api.templateByOrganizationAndName)
|
||||
})
|
||||
})
|
||||
r.Route("/parameters/{scope}/{id}", func(r chi.Router) {
|
||||
@@ -91,33 +91,33 @@ func New(options *Options) (http.Handler, func()) {
|
||||
r.Delete("/", api.deleteParameter)
|
||||
})
|
||||
})
|
||||
r.Route("/projects/{project}", func(r chi.Router) {
|
||||
r.Route("/templates/{template}", func(r chi.Router) {
|
||||
r.Use(
|
||||
httpmw.ExtractAPIKey(options.Database, nil),
|
||||
httpmw.ExtractProjectParam(options.Database),
|
||||
httpmw.ExtractTemplateParam(options.Database),
|
||||
httpmw.ExtractOrganizationParam(options.Database),
|
||||
)
|
||||
r.Get("/", api.project)
|
||||
r.Delete("/", api.deleteProject)
|
||||
r.Get("/", api.template)
|
||||
r.Delete("/", api.deleteTemplate)
|
||||
r.Route("/versions", func(r chi.Router) {
|
||||
r.Get("/", api.projectVersionsByProject)
|
||||
r.Patch("/", api.patchActiveProjectVersion)
|
||||
r.Get("/{projectversionname}", api.projectVersionByName)
|
||||
r.Get("/", api.templateVersionsByTemplate)
|
||||
r.Patch("/", api.patchActiveTemplateVersion)
|
||||
r.Get("/{templateversionname}", api.templateVersionByName)
|
||||
})
|
||||
})
|
||||
r.Route("/projectversions/{projectversion}", func(r chi.Router) {
|
||||
r.Route("/templateversions/{templateversion}", func(r chi.Router) {
|
||||
r.Use(
|
||||
httpmw.ExtractAPIKey(options.Database, nil),
|
||||
httpmw.ExtractProjectVersionParam(options.Database),
|
||||
httpmw.ExtractTemplateVersionParam(options.Database),
|
||||
httpmw.ExtractOrganizationParam(options.Database),
|
||||
)
|
||||
|
||||
r.Get("/", api.projectVersion)
|
||||
r.Patch("/cancel", api.patchCancelProjectVersion)
|
||||
r.Get("/schema", api.projectVersionSchema)
|
||||
r.Get("/parameters", api.projectVersionParameters)
|
||||
r.Get("/resources", api.projectVersionResources)
|
||||
r.Get("/logs", api.projectVersionLogs)
|
||||
r.Get("/", api.templateVersion)
|
||||
r.Patch("/cancel", api.patchCancelTemplateVersion)
|
||||
r.Get("/schema", api.templateVersionSchema)
|
||||
r.Get("/parameters", api.templateVersionParameters)
|
||||
r.Get("/resources", api.templateVersionResources)
|
||||
r.Get("/logs", api.templateVersionLogs)
|
||||
})
|
||||
r.Route("/provisionerdaemons", func(r chi.Router) {
|
||||
r.Route("/me", func(r chi.Router) {
|
||||
|
||||
@@ -203,44 +203,44 @@ func CreateAnotherUser(t *testing.T, client *codersdk.Client, organizationID uui
|
||||
return other
|
||||
}
|
||||
|
||||
// CreateProjectVersion creates a project import provisioner job
|
||||
// CreateTemplateVersion creates a template import provisioner job
|
||||
// with the responses provided. It uses the "echo" provisioner for compatibility
|
||||
// with testing.
|
||||
func CreateProjectVersion(t *testing.T, client *codersdk.Client, organizationID uuid.UUID, res *echo.Responses) codersdk.ProjectVersion {
|
||||
func CreateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID uuid.UUID, res *echo.Responses) codersdk.TemplateVersion {
|
||||
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(), organizationID, codersdk.CreateProjectVersionRequest{
|
||||
templateVersion, err := client.CreateTemplateVersion(context.Background(), organizationID, codersdk.CreateTemplateVersionRequest{
|
||||
StorageSource: file.Hash,
|
||||
StorageMethod: database.ProvisionerStorageMethodFile,
|
||||
Provisioner: database.ProvisionerTypeEcho,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return projectVersion
|
||||
return templateVersion
|
||||
}
|
||||
|
||||
// CreateProject creates a project with the "echo" provisioner for
|
||||
// CreateTemplate creates a template with the "echo" provisioner for
|
||||
// compatibility with testing. The name assigned is randomly generated.
|
||||
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{
|
||||
func CreateTemplate(t *testing.T, client *codersdk.Client, organization uuid.UUID, version uuid.UUID) codersdk.Template {
|
||||
template, err := client.CreateTemplate(context.Background(), organization, codersdk.CreateTemplateRequest{
|
||||
Name: randomUsername(),
|
||||
VersionID: version,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return project
|
||||
return template
|
||||
}
|
||||
|
||||
// AwaitProjectImportJob awaits for an import job to reach completed status.
|
||||
func AwaitProjectVersionJob(t *testing.T, client *codersdk.Client, version uuid.UUID) codersdk.ProjectVersion {
|
||||
var projectVersion codersdk.ProjectVersion
|
||||
// AwaitTemplateImportJob awaits for an import job to reach completed status.
|
||||
func AwaitTemplateVersionJob(t *testing.T, client *codersdk.Client, version uuid.UUID) codersdk.TemplateVersion {
|
||||
var templateVersion codersdk.TemplateVersion
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
projectVersion, err = client.ProjectVersion(context.Background(), version)
|
||||
templateVersion, err = client.TemplateVersion(context.Background(), version)
|
||||
require.NoError(t, err)
|
||||
return projectVersion.Job.CompletedAt != nil
|
||||
return templateVersion.Job.CompletedAt != nil
|
||||
}, 5*time.Second, 25*time.Millisecond)
|
||||
return projectVersion
|
||||
return templateVersion
|
||||
}
|
||||
|
||||
// AwaitWorkspaceBuildJob waits for a workspace provision job to reach completed status.
|
||||
@@ -275,12 +275,12 @@ func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, build uuid.UUID
|
||||
return resources
|
||||
}
|
||||
|
||||
// CreateWorkspace creates a workspace for the user and project provided.
|
||||
// CreateWorkspace creates a workspace for the user and template provided.
|
||||
// A random name is generated for it.
|
||||
func CreateWorkspace(t *testing.T, client *codersdk.Client, user uuid.UUID, projectID uuid.UUID) codersdk.Workspace {
|
||||
func CreateWorkspace(t *testing.T, client *codersdk.Client, user uuid.UUID, templateID uuid.UUID) codersdk.Workspace {
|
||||
workspace, err := client.CreateWorkspace(context.Background(), user, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: projectID,
|
||||
Name: randomUsername(),
|
||||
TemplateID: templateID,
|
||||
Name: randomUsername(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return workspace
|
||||
|
||||
@@ -18,10 +18,10 @@ func TestNew(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
closer := coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
_, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false)
|
||||
|
||||
@@ -22,8 +22,8 @@ func New() database.Store {
|
||||
files: make([]database.File, 0),
|
||||
parameterValue: make([]database.ParameterValue, 0),
|
||||
parameterSchema: make([]database.ParameterSchema, 0),
|
||||
project: make([]database.Project, 0),
|
||||
projectVersion: make([]database.ProjectVersion, 0),
|
||||
template: make([]database.Template, 0),
|
||||
templateVersion: make([]database.TemplateVersion, 0),
|
||||
provisionerDaemons: make([]database.ProvisionerDaemon, 0),
|
||||
provisionerJobs: make([]database.ProvisionerJob, 0),
|
||||
provisionerJobLog: make([]database.ProvisionerJobLog, 0),
|
||||
@@ -49,8 +49,8 @@ type fakeQuerier struct {
|
||||
files []database.File
|
||||
parameterValue []database.ParameterValue
|
||||
parameterSchema []database.ParameterSchema
|
||||
project []database.Project
|
||||
projectVersion []database.ProjectVersion
|
||||
template []database.Template
|
||||
templateVersion []database.TemplateVersion
|
||||
provisionerDaemons []database.ProvisionerDaemon
|
||||
provisionerJobs []database.ProvisionerJob
|
||||
provisionerJobAgent []database.WorkspaceAgent
|
||||
@@ -164,13 +164,13 @@ func (q *fakeQuerier) GetUserCount(_ context.Context) (int64, error) {
|
||||
return int64(len(q.users)), nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspacesByProjectID(_ context.Context, arg database.GetWorkspacesByProjectIDParams) ([]database.Workspace, error) {
|
||||
func (q *fakeQuerier) GetWorkspacesByTemplateID(_ context.Context, arg database.GetWorkspacesByTemplateIDParams) ([]database.Workspace, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
workspaces := make([]database.Workspace, 0)
|
||||
for _, workspace := range q.workspace {
|
||||
if workspace.ProjectID.String() != arg.ProjectID.String() {
|
||||
if workspace.TemplateID.String() != arg.TemplateID.String() {
|
||||
continue
|
||||
}
|
||||
if workspace.Deleted != arg.Deleted {
|
||||
@@ -215,38 +215,38 @@ func (q *fakeQuerier) GetWorkspaceByUserIDAndName(_ context.Context, arg databas
|
||||
return database.Workspace{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceOwnerCountsByProjectIDs(_ context.Context, projectIDs []uuid.UUID) ([]database.GetWorkspaceOwnerCountsByProjectIDsRow, error) {
|
||||
func (q *fakeQuerier) GetWorkspaceOwnerCountsByTemplateIDs(_ context.Context, templateIDs []uuid.UUID) ([]database.GetWorkspaceOwnerCountsByTemplateIDsRow, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
counts := map[uuid.UUID]map[uuid.UUID]struct{}{}
|
||||
for _, projectID := range projectIDs {
|
||||
for _, templateID := range templateIDs {
|
||||
found := false
|
||||
for _, workspace := range q.workspace {
|
||||
if workspace.ProjectID != projectID {
|
||||
if workspace.TemplateID != templateID {
|
||||
continue
|
||||
}
|
||||
if workspace.Deleted {
|
||||
continue
|
||||
}
|
||||
countByOwnerID, ok := counts[projectID]
|
||||
countByOwnerID, ok := counts[templateID]
|
||||
if !ok {
|
||||
countByOwnerID = map[uuid.UUID]struct{}{}
|
||||
}
|
||||
countByOwnerID[workspace.OwnerID] = struct{}{}
|
||||
counts[projectID] = countByOwnerID
|
||||
counts[templateID] = countByOwnerID
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if !found {
|
||||
counts[projectID] = map[uuid.UUID]struct{}{}
|
||||
counts[templateID] = map[uuid.UUID]struct{}{}
|
||||
}
|
||||
}
|
||||
res := make([]database.GetWorkspaceOwnerCountsByProjectIDsRow, 0)
|
||||
res := make([]database.GetWorkspaceOwnerCountsByTemplateIDsRow, 0)
|
||||
for key, value := range counts {
|
||||
res = append(res, database.GetWorkspaceOwnerCountsByProjectIDsRow{
|
||||
ProjectID: key,
|
||||
Count: int64(len(value)),
|
||||
res = append(res, database.GetWorkspaceOwnerCountsByTemplateIDsRow{
|
||||
TemplateID: key,
|
||||
Count: int64(len(value)),
|
||||
})
|
||||
}
|
||||
if len(res) == 0 {
|
||||
@@ -431,47 +431,47 @@ func (q *fakeQuerier) GetParameterValuesByScope(_ context.Context, arg database.
|
||||
return parameterValues, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectByID(_ context.Context, id uuid.UUID) (database.Project, error) {
|
||||
func (q *fakeQuerier) GetTemplateByID(_ context.Context, id uuid.UUID) (database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
for _, project := range q.project {
|
||||
if project.ID.String() == id.String() {
|
||||
return project, nil
|
||||
for _, template := range q.template {
|
||||
if template.ID.String() == id.String() {
|
||||
return template, nil
|
||||
}
|
||||
}
|
||||
return database.Project{}, sql.ErrNoRows
|
||||
return database.Template{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectByOrganizationAndName(_ context.Context, arg database.GetProjectByOrganizationAndNameParams) (database.Project, error) {
|
||||
func (q *fakeQuerier) GetTemplateByOrganizationAndName(_ context.Context, arg database.GetTemplateByOrganizationAndNameParams) (database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
for _, project := range q.project {
|
||||
if project.OrganizationID != arg.OrganizationID {
|
||||
for _, template := range q.template {
|
||||
if template.OrganizationID != arg.OrganizationID {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(project.Name, arg.Name) {
|
||||
if !strings.EqualFold(template.Name, arg.Name) {
|
||||
continue
|
||||
}
|
||||
if project.Deleted != arg.Deleted {
|
||||
if template.Deleted != arg.Deleted {
|
||||
continue
|
||||
}
|
||||
return project, nil
|
||||
return template, nil
|
||||
}
|
||||
return database.Project{}, sql.ErrNoRows
|
||||
return database.Template{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectVersionsByProjectID(_ context.Context, projectID uuid.UUID) ([]database.ProjectVersion, error) {
|
||||
func (q *fakeQuerier) GetTemplateVersionsByTemplateID(_ context.Context, templateID uuid.UUID) ([]database.TemplateVersion, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
version := make([]database.ProjectVersion, 0)
|
||||
for _, projectVersion := range q.projectVersion {
|
||||
if projectVersion.ProjectID.UUID.String() != projectID.String() {
|
||||
version := make([]database.TemplateVersion, 0)
|
||||
for _, templateVersion := range q.templateVersion {
|
||||
if templateVersion.TemplateID.UUID.String() != templateID.String() {
|
||||
continue
|
||||
}
|
||||
version = append(version, projectVersion)
|
||||
version = append(version, templateVersion)
|
||||
}
|
||||
if len(version) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
@@ -479,46 +479,46 @@ func (q *fakeQuerier) GetProjectVersionsByProjectID(_ context.Context, projectID
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectVersionByProjectIDAndName(_ context.Context, arg database.GetProjectVersionByProjectIDAndNameParams) (database.ProjectVersion, error) {
|
||||
func (q *fakeQuerier) GetTemplateVersionByTemplateIDAndName(_ context.Context, arg database.GetTemplateVersionByTemplateIDAndNameParams) (database.TemplateVersion, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
for _, projectVersion := range q.projectVersion {
|
||||
if projectVersion.ProjectID != arg.ProjectID {
|
||||
for _, templateVersion := range q.templateVersion {
|
||||
if templateVersion.TemplateID != arg.TemplateID {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(projectVersion.Name, arg.Name) {
|
||||
if !strings.EqualFold(templateVersion.Name, arg.Name) {
|
||||
continue
|
||||
}
|
||||
return projectVersion, nil
|
||||
return templateVersion, nil
|
||||
}
|
||||
return database.ProjectVersion{}, sql.ErrNoRows
|
||||
return database.TemplateVersion{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectVersionByID(_ context.Context, projectVersionID uuid.UUID) (database.ProjectVersion, error) {
|
||||
func (q *fakeQuerier) GetTemplateVersionByID(_ context.Context, templateVersionID uuid.UUID) (database.TemplateVersion, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
for _, projectVersion := range q.projectVersion {
|
||||
if projectVersion.ID.String() != projectVersionID.String() {
|
||||
for _, templateVersion := range q.templateVersion {
|
||||
if templateVersion.ID.String() != templateVersionID.String() {
|
||||
continue
|
||||
}
|
||||
return projectVersion, nil
|
||||
return templateVersion, nil
|
||||
}
|
||||
return database.ProjectVersion{}, sql.ErrNoRows
|
||||
return database.TemplateVersion{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectVersionByJobID(_ context.Context, jobID uuid.UUID) (database.ProjectVersion, error) {
|
||||
func (q *fakeQuerier) GetTemplateVersionByJobID(_ context.Context, jobID uuid.UUID) (database.TemplateVersion, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
for _, projectVersion := range q.projectVersion {
|
||||
if projectVersion.JobID.String() != jobID.String() {
|
||||
for _, templateVersion := range q.templateVersion {
|
||||
if templateVersion.JobID.String() != jobID.String() {
|
||||
continue
|
||||
}
|
||||
return projectVersion, nil
|
||||
return templateVersion, nil
|
||||
}
|
||||
return database.ProjectVersion{}, sql.ErrNoRows
|
||||
return database.TemplateVersion{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetParameterSchemasByJobID(_ context.Context, jobID uuid.UUID) ([]database.ParameterSchema, error) {
|
||||
@@ -557,43 +557,43 @@ func (q *fakeQuerier) GetParameterValueByScopeAndName(_ context.Context, arg dat
|
||||
return database.ParameterValue{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectsByOrganization(_ context.Context, arg database.GetProjectsByOrganizationParams) ([]database.Project, error) {
|
||||
func (q *fakeQuerier) GetTemplatesByOrganization(_ context.Context, arg database.GetTemplatesByOrganizationParams) ([]database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
projects := make([]database.Project, 0)
|
||||
for _, project := range q.project {
|
||||
if project.Deleted != arg.Deleted {
|
||||
templates := make([]database.Template, 0)
|
||||
for _, template := range q.template {
|
||||
if template.Deleted != arg.Deleted {
|
||||
continue
|
||||
}
|
||||
if project.OrganizationID != arg.OrganizationID {
|
||||
if template.OrganizationID != arg.OrganizationID {
|
||||
continue
|
||||
}
|
||||
projects = append(projects, project)
|
||||
templates = append(templates, template)
|
||||
}
|
||||
if len(projects) == 0 {
|
||||
if len(templates) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return projects, nil
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProjectsByIDs(_ context.Context, ids []uuid.UUID) ([]database.Project, error) {
|
||||
func (q *fakeQuerier) GetTemplatesByIDs(_ context.Context, ids []uuid.UUID) ([]database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
projects := make([]database.Project, 0)
|
||||
for _, project := range q.project {
|
||||
templates := make([]database.Template, 0)
|
||||
for _, template := range q.template {
|
||||
for _, id := range ids {
|
||||
if project.ID.String() != id.String() {
|
||||
if template.ID.String() != id.String() {
|
||||
continue
|
||||
}
|
||||
projects = append(projects, project)
|
||||
templates = append(templates, template)
|
||||
}
|
||||
}
|
||||
if len(projects) == 0 {
|
||||
if len(templates) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return projects, nil
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizationMemberByUserID(_ context.Context, arg database.GetOrganizationMemberByUserIDParams) (database.OrganizationMember, error) {
|
||||
@@ -850,12 +850,12 @@ func (q *fakeQuerier) InsertParameterValue(_ context.Context, arg database.Inser
|
||||
return parameterValue, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) InsertProject(_ context.Context, arg database.InsertProjectParams) (database.Project, error) {
|
||||
func (q *fakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTemplateParams) (database.Template, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
//nolint:gosimple
|
||||
project := database.Project{
|
||||
template := database.Template{
|
||||
ID: arg.ID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
@@ -864,18 +864,18 @@ func (q *fakeQuerier) InsertProject(_ context.Context, arg database.InsertProjec
|
||||
Provisioner: arg.Provisioner,
|
||||
ActiveVersionID: arg.ActiveVersionID,
|
||||
}
|
||||
q.project = append(q.project, project)
|
||||
return project, nil
|
||||
q.template = append(q.template, template)
|
||||
return template, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) InsertProjectVersion(_ context.Context, arg database.InsertProjectVersionParams) (database.ProjectVersion, error) {
|
||||
func (q *fakeQuerier) InsertTemplateVersion(_ context.Context, arg database.InsertTemplateVersionParams) (database.TemplateVersion, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
//nolint:gosimple
|
||||
version := database.ProjectVersion{
|
||||
version := database.TemplateVersion{
|
||||
ID: arg.ID,
|
||||
ProjectID: arg.ProjectID,
|
||||
TemplateID: arg.TemplateID,
|
||||
OrganizationID: arg.OrganizationID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
@@ -883,7 +883,7 @@ func (q *fakeQuerier) InsertProjectVersion(_ context.Context, arg database.Inser
|
||||
Description: arg.Description,
|
||||
JobID: arg.JobID,
|
||||
}
|
||||
q.projectVersion = append(q.projectVersion, version)
|
||||
q.templateVersion = append(q.templateVersion, version)
|
||||
return version, nil
|
||||
}
|
||||
|
||||
@@ -1033,12 +1033,12 @@ func (q *fakeQuerier) InsertWorkspace(_ context.Context, arg database.InsertWork
|
||||
|
||||
//nolint:gosimple
|
||||
workspace := database.Workspace{
|
||||
ID: arg.ID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
OwnerID: arg.OwnerID,
|
||||
ProjectID: arg.ProjectID,
|
||||
Name: arg.Name,
|
||||
ID: arg.ID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
OwnerID: arg.OwnerID,
|
||||
TemplateID: arg.TemplateID,
|
||||
Name: arg.Name,
|
||||
}
|
||||
q.workspace = append(q.workspace, workspace)
|
||||
return workspace, nil
|
||||
@@ -1049,17 +1049,17 @@ func (q *fakeQuerier) InsertWorkspaceBuild(_ context.Context, arg database.Inser
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
workspaceBuild := database.WorkspaceBuild{
|
||||
ID: arg.ID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
WorkspaceID: arg.WorkspaceID,
|
||||
Name: arg.Name,
|
||||
ProjectVersionID: arg.ProjectVersionID,
|
||||
BeforeID: arg.BeforeID,
|
||||
Transition: arg.Transition,
|
||||
InitiatorID: arg.InitiatorID,
|
||||
JobID: arg.JobID,
|
||||
ProvisionerState: arg.ProvisionerState,
|
||||
ID: arg.ID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
WorkspaceID: arg.WorkspaceID,
|
||||
Name: arg.Name,
|
||||
TemplateVersionID: arg.TemplateVersionID,
|
||||
BeforeID: arg.BeforeID,
|
||||
Transition: arg.Transition,
|
||||
InitiatorID: arg.InitiatorID,
|
||||
JobID: arg.JobID,
|
||||
ProvisionerState: arg.ProvisionerState,
|
||||
}
|
||||
q.workspaceBuild = append(q.workspaceBuild, workspaceBuild)
|
||||
return workspaceBuild, nil
|
||||
@@ -1084,47 +1084,47 @@ func (q *fakeQuerier) UpdateAPIKeyByID(_ context.Context, arg database.UpdateAPI
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateProjectActiveVersionByID(_ context.Context, arg database.UpdateProjectActiveVersionByIDParams) error {
|
||||
func (q *fakeQuerier) UpdateTemplateActiveVersionByID(_ context.Context, arg database.UpdateTemplateActiveVersionByIDParams) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
for index, project := range q.project {
|
||||
if project.ID.String() != arg.ID.String() {
|
||||
for index, template := range q.template {
|
||||
if template.ID.String() != arg.ID.String() {
|
||||
continue
|
||||
}
|
||||
project.ActiveVersionID = arg.ActiveVersionID
|
||||
q.project[index] = project
|
||||
template.ActiveVersionID = arg.ActiveVersionID
|
||||
q.template[index] = template
|
||||
return nil
|
||||
}
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateProjectDeletedByID(_ context.Context, arg database.UpdateProjectDeletedByIDParams) error {
|
||||
func (q *fakeQuerier) UpdateTemplateDeletedByID(_ context.Context, arg database.UpdateTemplateDeletedByIDParams) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
for index, project := range q.project {
|
||||
if project.ID.String() != arg.ID.String() {
|
||||
for index, template := range q.template {
|
||||
if template.ID.String() != arg.ID.String() {
|
||||
continue
|
||||
}
|
||||
project.Deleted = arg.Deleted
|
||||
q.project[index] = project
|
||||
template.Deleted = arg.Deleted
|
||||
q.template[index] = template
|
||||
return nil
|
||||
}
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateProjectVersionByID(_ context.Context, arg database.UpdateProjectVersionByIDParams) error {
|
||||
func (q *fakeQuerier) UpdateTemplateVersionByID(_ context.Context, arg database.UpdateTemplateVersionByIDParams) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
for index, projectVersion := range q.projectVersion {
|
||||
if projectVersion.ID.String() != arg.ID.String() {
|
||||
for index, templateVersion := range q.templateVersion {
|
||||
if templateVersion.ID.String() != arg.ID.String() {
|
||||
continue
|
||||
}
|
||||
projectVersion.ProjectID = arg.ProjectID
|
||||
projectVersion.UpdatedAt = arg.UpdatedAt
|
||||
q.projectVersion[index] = projectVersion
|
||||
templateVersion.TemplateID = arg.TemplateID
|
||||
templateVersion.UpdatedAt = arg.UpdatedAt
|
||||
q.templateVersion[index] = templateVersion
|
||||
return nil
|
||||
}
|
||||
return sql.ErrNoRows
|
||||
|
||||
Generated
+51
-51
@@ -27,7 +27,7 @@ CREATE TYPE parameter_destination_scheme AS ENUM (
|
||||
|
||||
CREATE TYPE parameter_scope AS ENUM (
|
||||
'organization',
|
||||
'project',
|
||||
'template',
|
||||
'import_job',
|
||||
'user',
|
||||
'workspace'
|
||||
@@ -44,7 +44,7 @@ CREATE TYPE parameter_type_system AS ENUM (
|
||||
);
|
||||
|
||||
CREATE TYPE provisioner_job_type AS ENUM (
|
||||
'project_version_import',
|
||||
'template_version_import',
|
||||
'workspace_build'
|
||||
);
|
||||
|
||||
@@ -160,28 +160,6 @@ CREATE TABLE parameter_values (
|
||||
destination_scheme parameter_destination_scheme NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE project_versions (
|
||||
id uuid NOT NULL,
|
||||
project_id uuid,
|
||||
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,
|
||||
description character varying(1048576) NOT NULL,
|
||||
job_id uuid NOT NULL
|
||||
);
|
||||
|
||||
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 uuid NOT NULL,
|
||||
deleted boolean DEFAULT false NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
active_version_id uuid NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE provisioner_daemons (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
@@ -219,6 +197,28 @@ CREATE TABLE provisioner_jobs (
|
||||
worker_id uuid
|
||||
);
|
||||
|
||||
CREATE TABLE template_versions (
|
||||
id uuid NOT NULL,
|
||||
template_id uuid,
|
||||
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,
|
||||
description character varying(1048576) NOT NULL,
|
||||
job_id uuid NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE templates (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
deleted boolean DEFAULT false NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
active_version_id uuid NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
id uuid NOT NULL,
|
||||
email text NOT NULL,
|
||||
@@ -252,7 +252,7 @@ CREATE TABLE workspace_builds (
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
workspace_id uuid NOT NULL,
|
||||
project_version_id uuid NOT NULL,
|
||||
template_version_id uuid NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
before_id uuid,
|
||||
after_id uuid,
|
||||
@@ -278,7 +278,7 @@ CREATE TABLE workspaces (
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
owner_id uuid NOT NULL,
|
||||
project_id uuid NOT NULL,
|
||||
template_id uuid NOT NULL,
|
||||
deleted boolean DEFAULT false NOT NULL,
|
||||
name character varying(64) NOT NULL
|
||||
);
|
||||
@@ -315,18 +315,6 @@ ALTER TABLE ONLY parameter_values
|
||||
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_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_organization_id_name_key UNIQUE (organization_id, name);
|
||||
|
||||
ALTER TABLE ONLY projects
|
||||
ADD CONSTRAINT projects_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY provisioner_daemons
|
||||
ADD CONSTRAINT provisioner_daemons_name_key UNIQUE (name);
|
||||
|
||||
@@ -339,6 +327,18 @@ ALTER TABLE ONLY provisioner_job_logs
|
||||
ALTER TABLE ONLY provisioner_jobs
|
||||
ADD CONSTRAINT provisioner_jobs_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY template_versions
|
||||
ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY template_versions
|
||||
ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name);
|
||||
|
||||
ALTER TABLE ONLY templates
|
||||
ADD CONSTRAINT templates_organization_id_name_key UNIQUE (organization_id, name);
|
||||
|
||||
ALTER TABLE ONLY templates
|
||||
ADD CONSTRAINT templates_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY users
|
||||
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||
|
||||
@@ -373,7 +373,7 @@ 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_projects_name_lower ON projects USING btree (lower((name)::text));
|
||||
CREATE UNIQUE INDEX idx_templates_name_lower ON templates USING btree (lower((name)::text));
|
||||
|
||||
CREATE UNIQUE INDEX idx_users_email ON users USING btree (email);
|
||||
|
||||
@@ -381,7 +381,7 @@ CREATE UNIQUE INDEX idx_users_username ON users USING btree (username);
|
||||
|
||||
CREATE UNIQUE INDEX idx_workspaces_name_lower ON workspaces USING btree (lower((name)::text));
|
||||
|
||||
CREATE UNIQUE INDEX projects_organization_id_name_idx ON projects USING btree (organization_id, name) WHERE (deleted = false);
|
||||
CREATE UNIQUE INDEX templates_organization_id_name_idx ON templates USING btree (organization_id, name) WHERE (deleted = false);
|
||||
|
||||
CREATE UNIQUE INDEX users_username_lower_idx ON users USING btree (lower(username));
|
||||
|
||||
@@ -402,21 +402,21 @@ ALTER TABLE ONLY organization_members
|
||||
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_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 template_versions
|
||||
ADD CONSTRAINT template_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY template_versions
|
||||
ADD CONSTRAINT template_versions_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY templates
|
||||
ADD CONSTRAINT templates_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;
|
||||
|
||||
@@ -424,7 +424,7 @@ ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_project_version_id_fkey FOREIGN KEY (project_version_id) REFERENCES project_versions(id) ON DELETE CASCADE;
|
||||
ADD CONSTRAINT workspace_builds_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY workspace_builds
|
||||
ADD CONSTRAINT workspace_builds_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
@@ -436,5 +436,5 @@ ALTER TABLE ONLY workspaces
|
||||
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;
|
||||
ADD CONSTRAINT workspaces_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE RESTRICT;
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
DROP TABLE project_versions;
|
||||
|
||||
DROP TABLE projects;
|
||||
DROP TYPE provisioner_type;
|
||||
|
||||
DROP TABLE files;
|
||||
@@ -0,0 +1,6 @@
|
||||
DROP TABLE template_versions;
|
||||
|
||||
DROP TABLE templates;
|
||||
DROP TYPE provisioner_type;
|
||||
|
||||
DROP TABLE files;
|
||||
+16
-16
@@ -1,4 +1,4 @@
|
||||
-- Store arbitrary data like project source code or avatars.
|
||||
-- Store arbitrary data like template source code or avatars.
|
||||
CREATE TABLE files (
|
||||
hash varchar(64) NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
@@ -11,37 +11,37 @@ CREATE TABLE files (
|
||||
|
||||
CREATE TYPE provisioner_type AS ENUM ('echo', 'terraform');
|
||||
|
||||
-- Project defines infrastructure that your software project
|
||||
-- Template defines infrastructure that your software template
|
||||
-- requires for development.
|
||||
CREATE TABLE projects (
|
||||
CREATE TABLE templates (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
-- Projects must be scoped to an organization.
|
||||
-- Templates must be scoped to an organization.
|
||||
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.
|
||||
-- Target's a Template 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
|
||||
-- Disallow templates to have the same name under
|
||||
-- the same organization.
|
||||
UNIQUE(organization_id, name)
|
||||
);
|
||||
|
||||
-- Enforces no active projects have the same name.
|
||||
CREATE UNIQUE INDEX ON projects (organization_id, name) WHERE deleted = FALSE;
|
||||
CREATE UNIQUE INDEX idx_projects_name_lower ON projects USING btree (lower(name));
|
||||
-- Enforces no active templates have the same name.
|
||||
CREATE UNIQUE INDEX ON templates (organization_id, name) WHERE deleted = FALSE;
|
||||
CREATE UNIQUE INDEX idx_templates_name_lower ON templates USING btree (lower(name));
|
||||
|
||||
-- Project Versions store historical project data. When a Project Version is imported,
|
||||
-- an "import" job is queued to parse parameters. A Project Version
|
||||
-- Template Versions store historical template data. When a Template Version is imported,
|
||||
-- an "import" job is queued to parse parameters. A Template Version
|
||||
-- can only be used if the import job succeeds.
|
||||
CREATE TABLE project_versions (
|
||||
CREATE TABLE template_versions (
|
||||
id uuid NOT NULL,
|
||||
-- This should be indexed. It is intentionally nullable.
|
||||
project_id uuid REFERENCES projects (id) ON DELETE CASCADE,
|
||||
template_id uuid REFERENCES templates (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,
|
||||
@@ -51,10 +51,10 @@ CREATE TABLE project_versions (
|
||||
-- Extracted from a README.md on import.
|
||||
-- Maximum of 1MB.
|
||||
description varchar(1048576) NOT NULL,
|
||||
-- The job ID for building the project version.
|
||||
-- The job ID for building the template version.
|
||||
job_id uuid NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
-- Disallow projects to have the same build name
|
||||
-- Disallow templates to have the same build name
|
||||
-- multiple times.
|
||||
UNIQUE(project_id, name)
|
||||
UNIQUE(template_id, name)
|
||||
);
|
||||
@@ -5,7 +5,7 @@ CREATE TABLE workspaces (
|
||||
-- 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,
|
||||
template_id uuid NOT NULL REFERENCES templates (id) ON DELETE RESTRICT,
|
||||
deleted boolean NOT NULL DEFAULT FALSE,
|
||||
name varchar(64) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
|
||||
@@ -11,7 +11,7 @@ CREATE TABLE IF NOT EXISTS provisioner_daemons (
|
||||
);
|
||||
|
||||
CREATE TYPE provisioner_job_type AS ENUM (
|
||||
'project_version_import',
|
||||
'template_version_import',
|
||||
'workspace_build'
|
||||
);
|
||||
|
||||
@@ -92,7 +92,7 @@ CREATE TABLE workspace_agents (
|
||||
|
||||
CREATE TYPE parameter_scope AS ENUM (
|
||||
'organization',
|
||||
'project',
|
||||
'template',
|
||||
'import_job',
|
||||
'user',
|
||||
'workspace'
|
||||
@@ -107,7 +107,7 @@ CREATE TYPE parameter_source_scheme AS ENUM('none', 'data');
|
||||
-- Supported schemes for a parameter destination.
|
||||
CREATE TYPE parameter_destination_scheme AS ENUM('none', 'environment_variable', 'provisioner_variable');
|
||||
|
||||
-- Stores project version parameters parsed on import.
|
||||
-- Stores template version parameters parsed on import.
|
||||
-- No secrets are stored here.
|
||||
--
|
||||
-- All parameter validation occurs server-side to process
|
||||
@@ -162,7 +162,7 @@ CREATE TABLE workspace_builds (
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
workspace_id uuid NOT NULL REFERENCES workspaces (id) ON DELETE CASCADE,
|
||||
project_version_id uuid NOT NULL REFERENCES project_versions (id) ON DELETE CASCADE,
|
||||
template_version_id uuid NOT NULL REFERENCES template_versions (id) ON DELETE CASCADE,
|
||||
name varchar(64) NOT NULL,
|
||||
before_id uuid,
|
||||
after_id uuid,
|
||||
|
||||
+44
-44
@@ -97,7 +97,7 @@ type ParameterScope string
|
||||
|
||||
const (
|
||||
ParameterScopeOrganization ParameterScope = "organization"
|
||||
ParameterScopeProject ParameterScope = "project"
|
||||
ParameterScopeTemplate ParameterScope = "template"
|
||||
ParameterScopeImportJob ParameterScope = "import_job"
|
||||
ParameterScopeUser ParameterScope = "user"
|
||||
ParameterScopeWorkspace ParameterScope = "workspace"
|
||||
@@ -156,8 +156,8 @@ func (e *ParameterTypeSystem) Scan(src interface{}) error {
|
||||
type ProvisionerJobType string
|
||||
|
||||
const (
|
||||
ProvisionerJobTypeProjectVersionImport ProvisionerJobType = "project_version_import"
|
||||
ProvisionerJobTypeWorkspaceBuild ProvisionerJobType = "workspace_build"
|
||||
ProvisionerJobTypeTemplateVersionImport ProvisionerJobType = "template_version_import"
|
||||
ProvisionerJobTypeWorkspaceBuild ProvisionerJobType = "workspace_build"
|
||||
)
|
||||
|
||||
func (e *ProvisionerJobType) Scan(src interface{}) error {
|
||||
@@ -316,28 +316,6 @@ type ParameterValue struct {
|
||||
DestinationScheme ParameterDestinationScheme `db:"destination_scheme" json:"destination_scheme"`
|
||||
}
|
||||
|
||||
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 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"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
}
|
||||
|
||||
type ProjectVersion struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
ProjectID uuid.NullUUID `db:"project_id" json:"project_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"`
|
||||
Description string `db:"description" json:"description"`
|
||||
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||
}
|
||||
|
||||
type ProvisionerDaemon struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
@@ -375,6 +353,28 @@ type ProvisionerJobLog struct {
|
||||
Output string `db:"output" json:"output"`
|
||||
}
|
||||
|
||||
type Template 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 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"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
}
|
||||
|
||||
type TemplateVersion struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
TemplateID uuid.NullUUID `db:"template_id" json:"template_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"`
|
||||
Description string `db:"description" json:"description"`
|
||||
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Email string `db:"email" json:"email"`
|
||||
@@ -388,13 +388,13 @@ type User struct {
|
||||
}
|
||||
|
||||
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 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"`
|
||||
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 uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
type WorkspaceAgent struct {
|
||||
@@ -414,18 +414,18 @@ type WorkspaceAgent struct {
|
||||
}
|
||||
|
||||
type WorkspaceBuild 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"`
|
||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||
ProjectVersionID uuid.UUID `db:"project_version_id" json:"project_version_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
BeforeID uuid.NullUUID `db:"before_id" json:"before_id"`
|
||||
AfterID uuid.NullUUID `db:"after_id" json:"after_id"`
|
||||
Transition WorkspaceTransition `db:"transition" json:"transition"`
|
||||
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"`
|
||||
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"`
|
||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
BeforeID uuid.NullUUID `db:"before_id" json:"before_id"`
|
||||
AfterID uuid.NullUUID `db:"after_id" json:"after_id"`
|
||||
Transition WorkspaceTransition `db:"transition" json:"transition"`
|
||||
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"`
|
||||
}
|
||||
|
||||
type WorkspaceResource struct {
|
||||
|
||||
+15
-15
@@ -22,19 +22,19 @@ type querier interface {
|
||||
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)
|
||||
GetProjectByID(ctx context.Context, id uuid.UUID) (Project, error)
|
||||
GetProjectByOrganizationAndName(ctx context.Context, arg GetProjectByOrganizationAndNameParams) (Project, error)
|
||||
GetProjectVersionByID(ctx context.Context, id uuid.UUID) (ProjectVersion, error)
|
||||
GetProjectVersionByJobID(ctx context.Context, jobID uuid.UUID) (ProjectVersion, error)
|
||||
GetProjectVersionByProjectIDAndName(ctx context.Context, arg GetProjectVersionByProjectIDAndNameParams) (ProjectVersion, error)
|
||||
GetProjectVersionsByProjectID(ctx context.Context, dollar_1 uuid.UUID) ([]ProjectVersion, error)
|
||||
GetProjectsByIDs(ctx context.Context, ids []uuid.UUID) ([]Project, error)
|
||||
GetProjectsByOrganization(ctx context.Context, arg GetProjectsByOrganizationParams) ([]Project, error)
|
||||
GetProvisionerDaemonByID(ctx context.Context, id uuid.UUID) (ProvisionerDaemon, error)
|
||||
GetProvisionerDaemons(ctx context.Context) ([]ProvisionerDaemon, error)
|
||||
GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (ProvisionerJob, error)
|
||||
GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID) ([]ProvisionerJob, error)
|
||||
GetProvisionerLogsByIDBetween(ctx context.Context, arg GetProvisionerLogsByIDBetweenParams) ([]ProvisionerJobLog, error)
|
||||
GetTemplateByID(ctx context.Context, id uuid.UUID) (Template, error)
|
||||
GetTemplateByOrganizationAndName(ctx context.Context, arg GetTemplateByOrganizationAndNameParams) (Template, error)
|
||||
GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (TemplateVersion, error)
|
||||
GetTemplateVersionByJobID(ctx context.Context, jobID uuid.UUID) (TemplateVersion, error)
|
||||
GetTemplateVersionByTemplateIDAndName(ctx context.Context, arg GetTemplateVersionByTemplateIDAndNameParams) (TemplateVersion, error)
|
||||
GetTemplateVersionsByTemplateID(ctx context.Context, dollar_1 uuid.UUID) ([]TemplateVersion, error)
|
||||
GetTemplatesByIDs(ctx context.Context, ids []uuid.UUID) ([]Template, error)
|
||||
GetTemplatesByOrganization(ctx context.Context, arg GetTemplatesByOrganizationParams) ([]Template, error)
|
||||
GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error)
|
||||
GetUserByID(ctx context.Context, id uuid.UUID) (User, error)
|
||||
GetUserCount(ctx context.Context) (int64, error)
|
||||
@@ -49,10 +49,10 @@ type querier interface {
|
||||
GetWorkspaceBuildsByWorkspaceIDsWithoutAfter(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error)
|
||||
GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Workspace, error)
|
||||
GetWorkspaceByUserIDAndName(ctx context.Context, arg GetWorkspaceByUserIDAndNameParams) (Workspace, error)
|
||||
GetWorkspaceOwnerCountsByProjectIDs(ctx context.Context, ids []uuid.UUID) ([]GetWorkspaceOwnerCountsByProjectIDsRow, error)
|
||||
GetWorkspaceOwnerCountsByTemplateIDs(ctx context.Context, ids []uuid.UUID) ([]GetWorkspaceOwnerCountsByTemplateIDsRow, error)
|
||||
GetWorkspaceResourceByID(ctx context.Context, id uuid.UUID) (WorkspaceResource, error)
|
||||
GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.UUID) ([]WorkspaceResource, error)
|
||||
GetWorkspacesByProjectID(ctx context.Context, arg GetWorkspacesByProjectIDParams) ([]Workspace, error)
|
||||
GetWorkspacesByTemplateID(ctx context.Context, arg GetWorkspacesByTemplateIDParams) ([]Workspace, error)
|
||||
GetWorkspacesByUserID(ctx context.Context, arg GetWorkspacesByUserIDParams) ([]Workspace, error)
|
||||
InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error)
|
||||
InsertFile(ctx context.Context, arg InsertFileParams) (File, error)
|
||||
@@ -61,11 +61,11 @@ type querier interface {
|
||||
InsertOrganizationMember(ctx context.Context, arg InsertOrganizationMemberParams) (OrganizationMember, error)
|
||||
InsertParameterSchema(ctx context.Context, arg InsertParameterSchemaParams) (ParameterSchema, error)
|
||||
InsertParameterValue(ctx context.Context, arg InsertParameterValueParams) (ParameterValue, error)
|
||||
InsertProject(ctx context.Context, arg InsertProjectParams) (Project, error)
|
||||
InsertProjectVersion(ctx context.Context, arg InsertProjectVersionParams) (ProjectVersion, error)
|
||||
InsertProvisionerDaemon(ctx context.Context, arg InsertProvisionerDaemonParams) (ProvisionerDaemon, error)
|
||||
InsertProvisionerJob(ctx context.Context, arg InsertProvisionerJobParams) (ProvisionerJob, error)
|
||||
InsertProvisionerJobLogs(ctx context.Context, arg InsertProvisionerJobLogsParams) ([]ProvisionerJobLog, error)
|
||||
InsertTemplate(ctx context.Context, arg InsertTemplateParams) (Template, error)
|
||||
InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) (TemplateVersion, error)
|
||||
InsertUser(ctx context.Context, arg InsertUserParams) (User, error)
|
||||
InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (Workspace, error)
|
||||
InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error)
|
||||
@@ -73,13 +73,13 @@ type querier interface {
|
||||
InsertWorkspaceResource(ctx context.Context, arg InsertWorkspaceResourceParams) (WorkspaceResource, error)
|
||||
UpdateAPIKeyByID(ctx context.Context, arg UpdateAPIKeyByIDParams) error
|
||||
UpdateGitSSHKey(ctx context.Context, arg UpdateGitSSHKeyParams) error
|
||||
UpdateProjectActiveVersionByID(ctx context.Context, arg UpdateProjectActiveVersionByIDParams) error
|
||||
UpdateProjectDeletedByID(ctx context.Context, arg UpdateProjectDeletedByIDParams) error
|
||||
UpdateProjectVersionByID(ctx context.Context, arg UpdateProjectVersionByIDParams) error
|
||||
UpdateProvisionerDaemonByID(ctx context.Context, arg UpdateProvisionerDaemonByIDParams) error
|
||||
UpdateProvisionerJobByID(ctx context.Context, arg UpdateProvisionerJobByIDParams) error
|
||||
UpdateProvisionerJobWithCancelByID(ctx context.Context, arg UpdateProvisionerJobWithCancelByIDParams) error
|
||||
UpdateProvisionerJobWithCompleteByID(ctx context.Context, arg UpdateProvisionerJobWithCompleteByIDParams) error
|
||||
UpdateTemplateActiveVersionByID(ctx context.Context, arg UpdateTemplateActiveVersionByIDParams) error
|
||||
UpdateTemplateDeletedByID(ctx context.Context, arg UpdateTemplateDeletedByIDParams) error
|
||||
UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) error
|
||||
UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg UpdateWorkspaceAgentConnectionByIDParams) error
|
||||
UpdateWorkspaceBuildByID(ctx context.Context, arg UpdateWorkspaceBuildByIDParams) error
|
||||
UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error
|
||||
|
||||
+496
-496
File diff suppressed because it is too large
Load Diff
@@ -1,56 +0,0 @@
|
||||
-- name: GetProjectVersionsByProjectID :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
project_versions
|
||||
WHERE
|
||||
project_id = $1 :: uuid;
|
||||
|
||||
-- name: GetProjectVersionByJobID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
project_versions
|
||||
WHERE
|
||||
job_id = $1;
|
||||
|
||||
-- name: GetProjectVersionByProjectIDAndName :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
project_versions
|
||||
WHERE
|
||||
project_id = $1
|
||||
AND "name" = $2;
|
||||
|
||||
-- name: GetProjectVersionByID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
project_versions
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
-- name: InsertProjectVersion :one
|
||||
INSERT INTO
|
||||
project_versions (
|
||||
id,
|
||||
project_id,
|
||||
organization_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
"name",
|
||||
description,
|
||||
job_id
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
|
||||
|
||||
-- name: UpdateProjectVersionByID :exec
|
||||
UPDATE
|
||||
project_versions
|
||||
SET
|
||||
project_id = $2,
|
||||
updated_at = $3
|
||||
WHERE
|
||||
id = $1;
|
||||
@@ -1,26 +1,26 @@
|
||||
-- name: GetProjectByID :one
|
||||
-- name: GetTemplateByID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
projects
|
||||
templates
|
||||
WHERE
|
||||
id = $1
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetProjectsByIDs :many
|
||||
-- name: GetTemplatesByIDs :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
projects
|
||||
templates
|
||||
WHERE
|
||||
id = ANY(@ids :: uuid [ ]);
|
||||
|
||||
-- name: GetProjectByOrganizationAndName :one
|
||||
-- name: GetTemplateByOrganizationAndName :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
projects
|
||||
templates
|
||||
WHERE
|
||||
organization_id = @organization_id
|
||||
AND deleted = @deleted
|
||||
@@ -28,18 +28,18 @@ WHERE
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetProjectsByOrganization :many
|
||||
-- name: GetTemplatesByOrganization :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
projects
|
||||
templates
|
||||
WHERE
|
||||
organization_id = $1
|
||||
AND deleted = $2;
|
||||
|
||||
-- name: InsertProject :one
|
||||
-- name: InsertTemplate :one
|
||||
INSERT INTO
|
||||
projects (
|
||||
templates (
|
||||
id,
|
||||
created_at,
|
||||
updated_at,
|
||||
@@ -51,17 +51,17 @@ INSERT INTO
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7) RETURNING *;
|
||||
|
||||
-- name: UpdateProjectActiveVersionByID :exec
|
||||
-- name: UpdateTemplateActiveVersionByID :exec
|
||||
UPDATE
|
||||
projects
|
||||
templates
|
||||
SET
|
||||
active_version_id = $2
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
-- name: UpdateProjectDeletedByID :exec
|
||||
-- name: UpdateTemplateDeletedByID :exec
|
||||
UPDATE
|
||||
projects
|
||||
templates
|
||||
SET
|
||||
deleted = $2
|
||||
WHERE
|
||||
@@ -0,0 +1,56 @@
|
||||
-- name: GetTemplateVersionsByTemplateID :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
template_id = $1 :: uuid;
|
||||
|
||||
-- name: GetTemplateVersionByJobID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
job_id = $1;
|
||||
|
||||
-- name: GetTemplateVersionByTemplateIDAndName :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
template_id = $1
|
||||
AND "name" = $2;
|
||||
|
||||
-- name: GetTemplateVersionByID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
-- name: InsertTemplateVersion :one
|
||||
INSERT INTO
|
||||
template_versions (
|
||||
id,
|
||||
template_id,
|
||||
organization_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
"name",
|
||||
description,
|
||||
job_id
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
|
||||
|
||||
-- name: UpdateTemplateVersionByID :exec
|
||||
UPDATE
|
||||
template_versions
|
||||
SET
|
||||
template_id = $2,
|
||||
updated_at = $3
|
||||
WHERE
|
||||
id = $1;
|
||||
@@ -62,7 +62,7 @@ INSERT INTO
|
||||
created_at,
|
||||
updated_at,
|
||||
workspace_id,
|
||||
project_version_id,
|
||||
template_version_id,
|
||||
before_id,
|
||||
"name",
|
||||
transition,
|
||||
|
||||
@@ -8,13 +8,13 @@ WHERE
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetWorkspacesByProjectID :many
|
||||
-- name: GetWorkspacesByTemplateID :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
project_id = $1
|
||||
template_id = $1
|
||||
AND deleted = $2;
|
||||
|
||||
-- name: GetWorkspacesByUserID :many
|
||||
@@ -36,16 +36,16 @@ WHERE
|
||||
AND deleted = @deleted
|
||||
AND LOWER("name") = LOWER(@name);
|
||||
|
||||
-- name: GetWorkspaceOwnerCountsByProjectIDs :many
|
||||
-- name: GetWorkspaceOwnerCountsByTemplateIDs :many
|
||||
SELECT
|
||||
project_id,
|
||||
template_id,
|
||||
COUNT(DISTINCT owner_id)
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
project_id = ANY(@ids :: uuid [ ])
|
||||
template_id = ANY(@ids :: uuid [ ])
|
||||
GROUP BY
|
||||
project_id,
|
||||
template_id,
|
||||
owner_id;
|
||||
|
||||
-- name: InsertWorkspace :one
|
||||
@@ -55,7 +55,7 @@ INSERT INTO
|
||||
created_at,
|
||||
updated_at,
|
||||
owner_id,
|
||||
project_id,
|
||||
template_id,
|
||||
name
|
||||
)
|
||||
VALUES
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestAgentGitSSHKey(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
daemonCloser := coderdtest.NewProvisionerDaemon(t, client)
|
||||
authToken := uuid.NewString()
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionDryRun: echo.ProvisionComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
@@ -106,8 +106,8 @@ func TestAgentGitSSHKey(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
daemonCloser.Close()
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package httpmw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
||||
type projectParamContextKey struct{}
|
||||
|
||||
// ProjectParam returns the project from the ExtractProjectParam handler.
|
||||
func ProjectParam(r *http.Request) database.Project {
|
||||
project, ok := r.Context().Value(projectParamContextKey{}).(database.Project)
|
||||
if !ok {
|
||||
panic("developer error: project param middleware not provided")
|
||||
}
|
||||
return project
|
||||
}
|
||||
|
||||
// ExtractProjectParam grabs a project from the "project" URL parameter.
|
||||
func ExtractProjectParam(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) {
|
||||
projectID, parsed := parseUUID(rw, r, "project")
|
||||
if !parsed {
|
||||
return
|
||||
}
|
||||
project, err := db.GetProjectByID(r.Context(), projectID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("project %q does not exist", projectID),
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), projectParamContextKey{}, project)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", project.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package httpmw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
||||
type projectVersionParamContextKey struct{}
|
||||
|
||||
// ProjectVersionParam returns the project version from the ExtractProjectVersionParam handler.
|
||||
func ProjectVersionParam(r *http.Request) database.ProjectVersion {
|
||||
projectVersion, ok := r.Context().Value(projectVersionParamContextKey{}).(database.ProjectVersion)
|
||||
if !ok {
|
||||
panic("developer error: project version param middleware not provided")
|
||||
}
|
||||
return projectVersion
|
||||
}
|
||||
|
||||
// ExtractProjectVersionParam grabs project version from the "projectversion" URL parameter.
|
||||
func ExtractProjectVersionParam(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) {
|
||||
projectVersionID, parsed := parseUUID(rw, r, "projectversion")
|
||||
if !parsed {
|
||||
return
|
||||
}
|
||||
projectVersion, err := db.GetProjectVersionByID(r.Context(), projectVersionID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("project version %q does not exist", projectVersionID),
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), projectVersionParamContextKey{}, projectVersion)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", projectVersion.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package httpmw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
||||
type templateParamContextKey struct{}
|
||||
|
||||
// TemplateParam returns the template from the ExtractTemplateParam handler.
|
||||
func TemplateParam(r *http.Request) database.Template {
|
||||
template, ok := r.Context().Value(templateParamContextKey{}).(database.Template)
|
||||
if !ok {
|
||||
panic("developer error: template param middleware not provided")
|
||||
}
|
||||
return template
|
||||
}
|
||||
|
||||
// ExtractTemplateParam grabs a template from the "template" URL parameter.
|
||||
func ExtractTemplateParam(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) {
|
||||
templateID, parsed := parseUUID(rw, r, "template")
|
||||
if !parsed {
|
||||
return
|
||||
}
|
||||
template, err := db.GetTemplateByID(r.Context(), templateID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("template %q does not exist", templateID),
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get template: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), templateParamContextKey{}, template)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", template.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"github.com/coder/coder/cryptorand"
|
||||
)
|
||||
|
||||
func TestProjectParam(t *testing.T) {
|
||||
func TestTemplateParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
setupAuthentication := func(db database.Store) (*http.Request, database.Organization) {
|
||||
@@ -84,7 +84,7 @@ func TestProjectParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(httpmw.ExtractProjectParam(db))
|
||||
rtr.Use(httpmw.ExtractTemplateParam(db))
|
||||
rtr.Get("/", nil)
|
||||
r, _ := setupAuthentication(db)
|
||||
rw := httptest.NewRecorder()
|
||||
@@ -99,11 +99,11 @@ func TestProjectParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(httpmw.ExtractProjectParam(db))
|
||||
rtr.Use(httpmw.ExtractTemplateParam(db))
|
||||
rtr.Get("/", nil)
|
||||
|
||||
r, _ := setupAuthentication(db)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("project", uuid.NewString())
|
||||
chi.RouteContext(r.Context()).URLParams.Add("template", uuid.NewString())
|
||||
rw := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rw, r)
|
||||
|
||||
@@ -116,11 +116,11 @@ func TestProjectParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(httpmw.ExtractProjectParam(db))
|
||||
rtr.Use(httpmw.ExtractTemplateParam(db))
|
||||
rtr.Get("/", nil)
|
||||
|
||||
r, _ := setupAuthentication(db)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("project", "not-a-uuid")
|
||||
chi.RouteContext(r.Context()).URLParams.Add("template", "not-a-uuid")
|
||||
rw := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rw, r)
|
||||
|
||||
@@ -129,28 +129,28 @@ func TestProjectParam(t *testing.T) {
|
||||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Project", func(t *testing.T) {
|
||||
t.Run("Template", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractProjectParam(db),
|
||||
httpmw.ExtractTemplateParam(db),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
)
|
||||
rtr.Get("/", func(rw http.ResponseWriter, r *http.Request) {
|
||||
_ = httpmw.ProjectParam(r)
|
||||
_ = httpmw.TemplateParam(r)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
r, org := setupAuthentication(db)
|
||||
project, err := db.InsertProject(context.Background(), database.InsertProjectParams{
|
||||
template, err := db.InsertTemplate(context.Background(), database.InsertTemplateParams{
|
||||
ID: uuid.New(),
|
||||
OrganizationID: org.ID,
|
||||
Name: "moo",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("project", project.ID.String())
|
||||
chi.RouteContext(r.Context()).URLParams.Add("template", template.ID.String())
|
||||
rw := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rw, r)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package httpmw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
||||
type templateVersionParamContextKey struct{}
|
||||
|
||||
// TemplateVersionParam returns the template version from the ExtractTemplateVersionParam handler.
|
||||
func TemplateVersionParam(r *http.Request) database.TemplateVersion {
|
||||
templateVersion, ok := r.Context().Value(templateVersionParamContextKey{}).(database.TemplateVersion)
|
||||
if !ok {
|
||||
panic("developer error: template version param middleware not provided")
|
||||
}
|
||||
return templateVersion
|
||||
}
|
||||
|
||||
// ExtractTemplateVersionParam grabs template version from the "templateversion" URL parameter.
|
||||
func ExtractTemplateVersionParam(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) {
|
||||
templateVersionID, parsed := parseUUID(rw, r, "templateversion")
|
||||
if !parsed {
|
||||
return
|
||||
}
|
||||
templateVersion, err := db.GetTemplateVersionByID(r.Context(), templateVersionID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("template version %q does not exist", templateVersionID),
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get template version: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), templateVersionParamContextKey{}, templateVersion)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", templateVersion.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
+15
-15
@@ -19,10 +19,10 @@ import (
|
||||
"github.com/coder/coder/cryptorand"
|
||||
)
|
||||
|
||||
func TestProjectVersionParam(t *testing.T) {
|
||||
func TestTemplateVersionParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
setupAuthentication := func(db database.Store) (*http.Request, database.Project) {
|
||||
setupAuthentication := func(db database.Store) (*http.Request, database.Template) {
|
||||
var (
|
||||
id, secret = randomAPIKeyParts()
|
||||
hashed = sha256.Sum256([]byte(secret))
|
||||
@@ -75,7 +75,7 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
project, err := db.InsertProject(context.Background(), database.InsertProjectParams{
|
||||
template, err := db.InsertTemplate(context.Background(), database.InsertTemplateParams{
|
||||
ID: uuid.New(),
|
||||
OrganizationID: organization.ID,
|
||||
Name: "moo",
|
||||
@@ -84,16 +84,16 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
|
||||
ctx := chi.NewRouteContext()
|
||||
ctx.URLParams.Add("organization", organization.Name)
|
||||
ctx.URLParams.Add("project", project.Name)
|
||||
ctx.URLParams.Add("template", template.Name)
|
||||
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, ctx))
|
||||
return r, project
|
||||
return r, template
|
||||
}
|
||||
|
||||
t.Run("None", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(httpmw.ExtractProjectVersionParam(db))
|
||||
rtr.Use(httpmw.ExtractTemplateVersionParam(db))
|
||||
rtr.Get("/", nil)
|
||||
r, _ := setupAuthentication(db)
|
||||
rw := httptest.NewRecorder()
|
||||
@@ -108,11 +108,11 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(httpmw.ExtractProjectVersionParam(db))
|
||||
rtr.Use(httpmw.ExtractTemplateVersionParam(db))
|
||||
rtr.Get("/", nil)
|
||||
|
||||
r, _ := setupAuthentication(db)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("projectversion", uuid.NewString())
|
||||
chi.RouteContext(r.Context()).URLParams.Add("templateversion", uuid.NewString())
|
||||
rw := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rw, r)
|
||||
|
||||
@@ -121,28 +121,28 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
require.Equal(t, http.StatusNotFound, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("ProjectVersion", func(t *testing.T) {
|
||||
t.Run("TemplateVersion", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
rtr := chi.NewRouter()
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractProjectVersionParam(db),
|
||||
httpmw.ExtractTemplateVersionParam(db),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
)
|
||||
rtr.Get("/", func(rw http.ResponseWriter, r *http.Request) {
|
||||
_ = httpmw.ProjectVersionParam(r)
|
||||
_ = httpmw.TemplateVersionParam(r)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
r, project := setupAuthentication(db)
|
||||
projectVersion, err := db.InsertProjectVersion(context.Background(), database.InsertProjectVersionParams{
|
||||
r, template := setupAuthentication(db)
|
||||
templateVersion, err := db.InsertTemplateVersion(context.Background(), database.InsertTemplateVersionParams{
|
||||
ID: uuid.New(),
|
||||
OrganizationID: project.OrganizationID,
|
||||
OrganizationID: template.OrganizationID,
|
||||
Name: "moo",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("projectversion", projectVersion.ID.String())
|
||||
chi.RouteContext(r.Context()).URLParams.Add("templateversion", templateVersion.ID.String())
|
||||
rw := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rw, r)
|
||||
|
||||
@@ -58,10 +58,10 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
workspace, err := db.InsertWorkspace(context.Background(), database.InsertWorkspaceParams{
|
||||
ID: uuid.New(),
|
||||
ProjectID: uuid.New(),
|
||||
OwnerID: user.ID,
|
||||
Name: "potato",
|
||||
ID: uuid.New(),
|
||||
TemplateID: uuid.New(),
|
||||
OwnerID: user.ID,
|
||||
Name: "potato",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
type workspaceResourceParamContextKey struct{}
|
||||
|
||||
// ProvisionerJobParam returns the project from the ExtractProjectParam handler.
|
||||
// ProvisionerJobParam returns the template from the ExtractTemplateParam handler.
|
||||
func WorkspaceResourceParam(r *http.Request) database.WorkspaceResource {
|
||||
resource, ok := r.Context().Value(workspaceResourceParamContextKey{}).(database.WorkspaceResource)
|
||||
if !ok {
|
||||
|
||||
@@ -88,7 +88,7 @@ func TestWorkspaceResourceParam(t *testing.T) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
r, job := setup(db, database.ProvisionerJobTypeProjectVersionImport)
|
||||
r, job := setup(db, database.ProvisionerJobTypeTemplateVersionImport)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("workspaceresource", job.ID.String())
|
||||
rw := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rw, r)
|
||||
|
||||
+60
-60
@@ -42,25 +42,25 @@ func (api *api) provisionerDaemonsByOrganization(rw http.ResponseWriter, r *http
|
||||
render.JSON(rw, r, daemons)
|
||||
}
|
||||
|
||||
// Creates a new version of a project. An import job is queued to parse the storage method provided.
|
||||
func (api *api) postProjectVersionsByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
// Creates a new version of a template. An import job is queued to parse the storage method provided.
|
||||
func (api *api) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
apiKey := httpmw.APIKey(r)
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
var req codersdk.CreateProjectVersionRequest
|
||||
var req codersdk.CreateTemplateVersionRequest
|
||||
if !httpapi.Read(rw, r, &req) {
|
||||
return
|
||||
}
|
||||
if req.ProjectID != uuid.Nil {
|
||||
_, err := api.Database.GetProjectByID(r.Context(), req.ProjectID)
|
||||
if req.TemplateID != uuid.Nil {
|
||||
_, err := api.Database.GetTemplateByID(r.Context(), req.TemplateID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: "project does not exist",
|
||||
Message: "template does not exist",
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project: %s", err),
|
||||
Message: fmt.Sprintf("get template: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func (api *api) postProjectVersionsByOrganization(rw http.ResponseWriter, r *htt
|
||||
return
|
||||
}
|
||||
|
||||
var projectVersion database.ProjectVersion
|
||||
var templateVersion database.TemplateVersion
|
||||
var provisionerJob database.ProvisionerJob
|
||||
err = api.Database.InTx(func(db database.Store) error {
|
||||
jobID := uuid.New()
|
||||
@@ -110,24 +110,24 @@ func (api *api) postProjectVersionsByOrganization(rw http.ResponseWriter, r *htt
|
||||
Provisioner: req.Provisioner,
|
||||
StorageMethod: database.ProvisionerStorageMethodFile,
|
||||
StorageSource: file.Hash,
|
||||
Type: database.ProvisionerJobTypeProjectVersionImport,
|
||||
Type: database.ProvisionerJobTypeTemplateVersionImport,
|
||||
Input: []byte{'{', '}'},
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert provisioner job: %w", err)
|
||||
}
|
||||
|
||||
var projectID uuid.NullUUID
|
||||
if req.ProjectID != uuid.Nil {
|
||||
projectID = uuid.NullUUID{
|
||||
UUID: req.ProjectID,
|
||||
var templateID uuid.NullUUID
|
||||
if req.TemplateID != uuid.Nil {
|
||||
templateID = uuid.NullUUID{
|
||||
UUID: req.TemplateID,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
projectVersion, err = api.Database.InsertProjectVersion(r.Context(), database.InsertProjectVersionParams{
|
||||
templateVersion, err = api.Database.InsertTemplateVersion(r.Context(), database.InsertTemplateVersionParams{
|
||||
ID: uuid.New(),
|
||||
ProjectID: projectID,
|
||||
TemplateID: templateID,
|
||||
OrganizationID: organization.ID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
@@ -136,7 +136,7 @@ func (api *api) postProjectVersionsByOrganization(rw http.ResponseWriter, r *htt
|
||||
JobID: provisionerJob.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert project version: %w", err)
|
||||
return xerrors.Errorf("insert template version: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -148,23 +148,23 @@ func (api *api) postProjectVersionsByOrganization(rw http.ResponseWriter, r *htt
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(rw, r, convertProjectVersion(projectVersion, convertProvisionerJob(provisionerJob)))
|
||||
render.JSON(rw, r, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob)))
|
||||
}
|
||||
|
||||
// Create a new project in an organization.
|
||||
func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
var createProject codersdk.CreateProjectRequest
|
||||
if !httpapi.Read(rw, r, &createProject) {
|
||||
// Create a new template in an organization.
|
||||
func (api *api) postTemplatesByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
var createTemplate codersdk.CreateTemplateRequest
|
||||
if !httpapi.Read(rw, r, &createTemplate) {
|
||||
return
|
||||
}
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
_, err := api.Database.GetProjectByOrganizationAndName(r.Context(), database.GetProjectByOrganizationAndNameParams{
|
||||
_, err := api.Database.GetTemplateByOrganizationAndName(r.Context(), database.GetTemplateByOrganizationAndNameParams{
|
||||
OrganizationID: organization.ID,
|
||||
Name: createProject.Name,
|
||||
Name: createTemplate.Name,
|
||||
})
|
||||
if err == nil {
|
||||
httpapi.Write(rw, http.StatusConflict, httpapi.Response{
|
||||
Message: fmt.Sprintf("project %q already exists", createProject.Name),
|
||||
Message: fmt.Sprintf("template %q already exists", createTemplate.Name),
|
||||
Errors: []httpapi.Error{{
|
||||
Field: "name",
|
||||
Code: "exists",
|
||||
@@ -174,23 +174,23 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project by name: %s", err),
|
||||
Message: fmt.Sprintf("get template by name: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
projectVersion, err := api.Database.GetProjectVersionByID(r.Context(), createProject.VersionID)
|
||||
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), createTemplate.VersionID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: "project version does not exist",
|
||||
Message: "template version does not exist",
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version by id: %s", err),
|
||||
Message: fmt.Sprintf("get template version by id: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
importJob, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
importJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get import job by id: %s", err),
|
||||
@@ -198,41 +198,41 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
||||
return
|
||||
}
|
||||
|
||||
var project codersdk.Project
|
||||
var template codersdk.Template
|
||||
err = api.Database.InTx(func(db database.Store) error {
|
||||
now := database.Now()
|
||||
dbProject, err := db.InsertProject(r.Context(), database.InsertProjectParams{
|
||||
dbTemplate, err := db.InsertTemplate(r.Context(), database.InsertTemplateParams{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
OrganizationID: organization.ID,
|
||||
Name: createProject.Name,
|
||||
Name: createTemplate.Name,
|
||||
Provisioner: importJob.Provisioner,
|
||||
ActiveVersionID: projectVersion.ID,
|
||||
ActiveVersionID: templateVersion.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert project: %s", err)
|
||||
return xerrors.Errorf("insert template: %s", err)
|
||||
}
|
||||
|
||||
err = db.UpdateProjectVersionByID(r.Context(), database.UpdateProjectVersionByIDParams{
|
||||
ID: projectVersion.ID,
|
||||
ProjectID: uuid.NullUUID{
|
||||
UUID: dbProject.ID,
|
||||
err = db.UpdateTemplateVersionByID(r.Context(), database.UpdateTemplateVersionByIDParams{
|
||||
ID: templateVersion.ID,
|
||||
TemplateID: uuid.NullUUID{
|
||||
UUID: dbTemplate.ID,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert project version: %s", err)
|
||||
return xerrors.Errorf("insert template version: %s", err)
|
||||
}
|
||||
|
||||
for _, parameterValue := range createProject.ParameterValues {
|
||||
for _, parameterValue := range createTemplate.ParameterValues {
|
||||
_, err = db.InsertParameterValue(r.Context(), database.InsertParameterValueParams{
|
||||
ID: uuid.New(),
|
||||
Name: parameterValue.Name,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
Scope: database.ParameterScopeProject,
|
||||
ScopeID: dbProject.ID,
|
||||
Scope: database.ParameterScopeTemplate,
|
||||
ScopeID: dbTemplate.ID,
|
||||
SourceScheme: parameterValue.SourceScheme,
|
||||
SourceValue: parameterValue.SourceValue,
|
||||
DestinationScheme: parameterValue.DestinationScheme,
|
||||
@@ -242,7 +242,7 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
}
|
||||
|
||||
project = convertProject(dbProject, 0)
|
||||
template = convertTemplate(dbTemplate, 0)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -253,12 +253,12 @@ func (api *api) postProjectsByOrganization(rw http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(rw, r, project)
|
||||
render.JSON(rw, r, template)
|
||||
}
|
||||
|
||||
func (api *api) projectsByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *api) templatesByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
projects, err := api.Database.GetProjectsByOrganization(r.Context(), database.GetProjectsByOrganizationParams{
|
||||
templates, err := api.Database.GetTemplatesByOrganization(r.Context(), database.GetTemplatesByOrganizationParams{
|
||||
OrganizationID: organization.ID,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
@@ -266,15 +266,15 @@ func (api *api) projectsByOrganization(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get projects: %s", err.Error()),
|
||||
Message: fmt.Sprintf("get templates: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
projectIDs := make([]uuid.UUID, 0, len(projects))
|
||||
for _, project := range projects {
|
||||
projectIDs = append(projectIDs, project.ID)
|
||||
templateIDs := make([]uuid.UUID, 0, len(templates))
|
||||
for _, template := range templates {
|
||||
templateIDs = append(templateIDs, template.ID)
|
||||
}
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByProjectIDs(r.Context(), projectIDs)
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByTemplateIDs(r.Context(), templateIDs)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
@@ -285,31 +285,31 @@ func (api *api) projectsByOrganization(rw http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertProjects(projects, workspaceCounts))
|
||||
render.JSON(rw, r, convertTemplates(templates, workspaceCounts))
|
||||
}
|
||||
|
||||
func (api *api) projectByOrganizationAndName(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *api) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Request) {
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
projectName := chi.URLParam(r, "projectname")
|
||||
project, err := api.Database.GetProjectByOrganizationAndName(r.Context(), database.GetProjectByOrganizationAndNameParams{
|
||||
templateName := chi.URLParam(r, "templatename")
|
||||
template, err := api.Database.GetTemplateByOrganizationAndName(r.Context(), database.GetTemplateByOrganizationAndNameParams{
|
||||
OrganizationID: organization.ID,
|
||||
Name: projectName,
|
||||
Name: templateName,
|
||||
})
|
||||
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),
|
||||
Message: fmt.Sprintf("no template found by name %q in the %q organization", templateName, organization.Name),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project by organization and name: %s", err),
|
||||
Message: fmt.Sprintf("get template by organization and name: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByProjectIDs(r.Context(), []uuid.UUID{project.ID})
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByTemplateIDs(r.Context(), []uuid.UUID{template.ID})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
@@ -326,7 +326,7 @@ func (api *api) projectByOrganizationAndName(rw http.ResponseWriter, r *http.Req
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertProject(project, count))
|
||||
render.JSON(rw, r, convertTemplate(template, count))
|
||||
}
|
||||
|
||||
// convertOrganization consumes the database representation and outputs an API friendly representation.
|
||||
|
||||
@@ -32,15 +32,15 @@ func TestProvisionerDaemonsByOrganization(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestPostProjectVersionsByOrganization(t *testing.T) {
|
||||
func TestPostTemplateVersionsByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("InvalidProject", func(t *testing.T) {
|
||||
t.Run("InvalidTemplate", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
projectID := uuid.New()
|
||||
_, err := client.CreateProjectVersion(context.Background(), user.OrganizationID, codersdk.CreateProjectVersionRequest{
|
||||
ProjectID: projectID,
|
||||
templateID := uuid.New()
|
||||
_, err := client.CreateTemplateVersion(context.Background(), user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
||||
TemplateID: templateID,
|
||||
StorageMethod: database.ProvisionerStorageMethodFile,
|
||||
StorageSource: "hash",
|
||||
Provisioner: database.ProvisionerTypeEcho,
|
||||
@@ -54,7 +54,7 @@ func TestPostProjectVersionsByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateProjectVersion(context.Background(), user.OrganizationID, codersdk.CreateProjectVersionRequest{
|
||||
_, err := client.CreateTemplateVersion(context.Background(), user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
||||
StorageMethod: database.ProvisionerStorageMethodFile,
|
||||
StorageSource: "hash",
|
||||
Provisioner: database.ProvisionerTypeEcho,
|
||||
@@ -76,7 +76,7 @@ func TestPostProjectVersionsByOrganization(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, data)
|
||||
require.NoError(t, err)
|
||||
_, err = client.CreateProjectVersion(context.Background(), user.OrganizationID, codersdk.CreateProjectVersionRequest{
|
||||
_, err = client.CreateTemplateVersion(context.Background(), user.OrganizationID, codersdk.CreateTemplateVersionRequest{
|
||||
StorageMethod: database.ProvisionerStorageMethodFile,
|
||||
StorageSource: file.Hash,
|
||||
Provisioner: database.ProvisionerTypeEcho,
|
||||
@@ -91,24 +91,24 @@ func TestPostProjectVersionsByOrganization(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestPostProjectsByOrganization(t *testing.T) {
|
||||
func TestPostTemplatesByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Create", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
})
|
||||
|
||||
t.Run("AlreadyExists", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.CreateProject(context.Background(), user.OrganizationID, codersdk.CreateProjectRequest{
|
||||
Name: project.Name,
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.CreateTemplate(context.Background(), user.OrganizationID, codersdk.CreateTemplateRequest{
|
||||
Name: template.Name,
|
||||
VersionID: version.ID,
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
@@ -120,7 +120,7 @@ func TestPostProjectsByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateProject(context.Background(), user.OrganizationID, codersdk.CreateProjectRequest{
|
||||
_, err := client.CreateTemplate(context.Background(), user.OrganizationID, codersdk.CreateTemplateRequest{
|
||||
Name: "test",
|
||||
VersionID: uuid.New(),
|
||||
})
|
||||
@@ -130,48 +130,48 @@ func TestPostProjectsByOrganization(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectsByOrganization(t *testing.T) {
|
||||
func TestTemplatesByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("ListEmpty", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
projects, err := client.ProjectsByOrganization(context.Background(), user.OrganizationID)
|
||||
templates, err := client.TemplatesByOrganization(context.Background(), user.OrganizationID)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, projects)
|
||||
require.Len(t, projects, 0)
|
||||
require.NotNil(t, templates)
|
||||
require.Len(t, templates, 0)
|
||||
})
|
||||
|
||||
t.Run("List", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
projects, err := client.ProjectsByOrganization(context.Background(), user.OrganizationID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
templates, err := client.TemplatesByOrganization(context.Background(), user.OrganizationID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, projects, 1)
|
||||
require.Len(t, templates, 1)
|
||||
})
|
||||
t.Run("ListMultiple", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
projects, err := client.ProjectsByOrganization(context.Background(), user.OrganizationID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
templates, err := client.TemplatesByOrganization(context.Background(), user.OrganizationID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, projects, 2)
|
||||
require.Len(t, templates, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectByOrganizationAndName(t *testing.T) {
|
||||
func TestTemplateByOrganizationAndName(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotFound", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.ProjectByName(context.Background(), user.OrganizationID, "something")
|
||||
_, err := client.TemplateByName(context.Background(), user.OrganizationID, "something")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
@@ -181,9 +181,9 @@ func TestProjectByOrganizationAndName(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.ProjectByName(context.Background(), user.OrganizationID, project.Name)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.TemplateByName(context.Background(), user.OrganizationID, template.Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
+17
-17
@@ -13,11 +13,11 @@ import (
|
||||
|
||||
// ComputeScope targets identifiers to pull parameters from.
|
||||
type ComputeScope struct {
|
||||
ProjectImportJobID uuid.UUID
|
||||
OrganizationID uuid.UUID
|
||||
UserID uuid.UUID
|
||||
ProjectID uuid.NullUUID
|
||||
WorkspaceID uuid.NullUUID
|
||||
TemplateImportJobID uuid.UUID
|
||||
OrganizationID uuid.UUID
|
||||
UserID uuid.UUID
|
||||
TemplateID uuid.NullUUID
|
||||
WorkspaceID uuid.NullUUID
|
||||
}
|
||||
|
||||
type ComputeOptions struct {
|
||||
@@ -48,12 +48,12 @@ func Compute(ctx context.Context, db database.Store, scope ComputeScope, options
|
||||
}
|
||||
|
||||
// All parameters for the import job ID!
|
||||
parameterSchemas, err := db.GetParameterSchemasByJobID(ctx, scope.ProjectImportJobID)
|
||||
parameterSchemas, err := db.GetParameterSchemasByJobID(ctx, scope.TemplateImportJobID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get project parameters: %w", err)
|
||||
return nil, xerrors.Errorf("get template parameters: %w", err)
|
||||
}
|
||||
for _, parameterSchema := range parameterSchemas {
|
||||
compute.parameterSchemasByName[parameterSchema.Name] = parameterSchema
|
||||
@@ -71,13 +71,13 @@ 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,
|
||||
ScopeID: scope.TemplateImportJobID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Default project parameter values come second!
|
||||
// Default template parameter values come second!
|
||||
for _, parameterSchema := range parameterSchemas {
|
||||
if parameterSchema.DefaultSourceScheme == database.ParameterSourceSchemeNone {
|
||||
continue
|
||||
@@ -101,21 +101,21 @@ func Compute(ctx context.Context, db database.Store, scope ComputeScope, options
|
||||
DestinationScheme: parameterSchema.DefaultDestinationScheme,
|
||||
SourceValue: parameterSchema.DefaultSourceValue,
|
||||
Scope: database.ParameterScopeImportJob,
|
||||
ScopeID: scope.ProjectImportJobID,
|
||||
ScopeID: scope.TemplateImportJobID,
|
||||
}, true)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("insert default value: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, xerrors.Errorf("unsupported source scheme for project version parameter %q: %q", parameterSchema.Name, string(parameterSchema.DefaultSourceScheme))
|
||||
return nil, xerrors.Errorf("unsupported source scheme for template version parameter %q: %q", parameterSchema.Name, string(parameterSchema.DefaultSourceScheme))
|
||||
}
|
||||
}
|
||||
|
||||
if scope.ProjectID.Valid {
|
||||
// Project parameters come third!
|
||||
if scope.TemplateID.Valid {
|
||||
// Template parameters come third!
|
||||
err = compute.injectScope(ctx, database.GetParameterValuesByScopeParams{
|
||||
Scope: database.ParameterScopeProject,
|
||||
ScopeID: scope.ProjectID.UUID,
|
||||
Scope: database.ParameterScopeTemplate,
|
||||
ScopeID: scope.TemplateID.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -178,14 +178,14 @@ func (c *compute) injectScope(ctx context.Context, scopeParams database.GetParam
|
||||
func (c *compute) injectSingle(scopedParameter database.ParameterValue, defaultValue bool) error {
|
||||
parameterSchema, hasParameterSchema := c.parameterSchemasByName[scopedParameter.Name]
|
||||
if !hasParameterSchema {
|
||||
// Don't inject parameters that aren't defined by the project.
|
||||
// Don't inject parameters that aren't defined by the template.
|
||||
return nil
|
||||
}
|
||||
|
||||
_, hasParameterValue := c.computedParameterByName[scopedParameter.Name]
|
||||
if hasParameterValue {
|
||||
if !parameterSchema.AllowOverrideSource &&
|
||||
// Users and workspaces cannot override anything on a project!
|
||||
// Users and workspaces cannot override anything on a template!
|
||||
(scopedParameter.Scope == database.ParameterScopeUser ||
|
||||
scopedParameter.Scope == database.ParameterScopeWorkspace) {
|
||||
return nil
|
||||
|
||||
@@ -17,9 +17,9 @@ func TestCompute(t *testing.T) {
|
||||
t.Parallel()
|
||||
generateScope := func() parameter.ComputeScope {
|
||||
return parameter.ComputeScope{
|
||||
ProjectImportJobID: uuid.New(),
|
||||
OrganizationID: uuid.New(),
|
||||
ProjectID: uuid.NullUUID{
|
||||
TemplateImportJobID: uuid.New(),
|
||||
OrganizationID: uuid.New(),
|
||||
TemplateID: uuid.NullUUID{
|
||||
UUID: uuid.New(),
|
||||
Valid: true,
|
||||
},
|
||||
@@ -34,7 +34,7 @@ func TestCompute(t *testing.T) {
|
||||
AllowOverrideSource bool
|
||||
AllowOverrideDestination bool
|
||||
DefaultDestinationScheme database.ParameterDestinationScheme
|
||||
ProjectImportJobID uuid.UUID
|
||||
TemplateImportJobID uuid.UUID
|
||||
}
|
||||
generateParameter := func(t *testing.T, db database.Store, opts parameterOptions) database.ParameterSchema {
|
||||
if opts.DefaultDestinationScheme == "" {
|
||||
@@ -47,7 +47,7 @@ func TestCompute(t *testing.T) {
|
||||
param, err := db.InsertParameterSchema(context.Background(), database.InsertParameterSchemaParams{
|
||||
ID: uuid.New(),
|
||||
Name: name,
|
||||
JobID: opts.ProjectImportJobID,
|
||||
JobID: opts.TemplateImportJobID,
|
||||
DefaultSourceScheme: database.ParameterSourceSchemeData,
|
||||
DefaultSourceValue: sourceValue,
|
||||
AllowOverrideSource: opts.AllowOverrideSource,
|
||||
@@ -64,7 +64,7 @@ func TestCompute(t *testing.T) {
|
||||
scope := generateScope()
|
||||
_, err := db.InsertParameterSchema(context.Background(), database.InsertParameterSchemaParams{
|
||||
ID: uuid.New(),
|
||||
JobID: scope.ProjectImportJobID,
|
||||
JobID: scope.TemplateImportJobID,
|
||||
Name: "hey",
|
||||
DefaultSourceScheme: database.ParameterSourceSchemeNone,
|
||||
})
|
||||
@@ -74,12 +74,12 @@ func TestCompute(t *testing.T) {
|
||||
require.Len(t, computed, 0)
|
||||
})
|
||||
|
||||
t.Run("UseDefaultProjectValue", func(t *testing.T) {
|
||||
t.Run("UseDefaultTemplateValue", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
scope := generateScope()
|
||||
parameterSchema := generateParameter(t, db, parameterOptions{
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
TemplateImportJobID: scope.TemplateImportJobID,
|
||||
DefaultDestinationScheme: database.ParameterDestinationSchemeProvisionerVariable,
|
||||
})
|
||||
computed, err := parameter.Compute(context.Background(), db, scope, nil)
|
||||
@@ -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, computedValue.ScopeID)
|
||||
require.Equal(t, scope.TemplateImportJobID, computedValue.ScopeID)
|
||||
require.Equal(t, computedValue.SourceValue, parameterSchema.DefaultSourceValue)
|
||||
})
|
||||
|
||||
@@ -97,7 +97,7 @@ func TestCompute(t *testing.T) {
|
||||
db := databasefake.New()
|
||||
scope := generateScope()
|
||||
parameterSchema := generateParameter(t, db, parameterOptions{
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
TemplateImportJobID: scope.TemplateImportJobID,
|
||||
})
|
||||
_, err := db.InsertParameterValue(context.Background(), database.InsertParameterValueParams{
|
||||
ID: uuid.New(),
|
||||
@@ -114,7 +114,7 @@ func TestCompute(t *testing.T) {
|
||||
ID: uuid.New(),
|
||||
Name: parameterSchema.Name,
|
||||
Scope: database.ParameterScopeImportJob,
|
||||
ScopeID: scope.ProjectImportJobID,
|
||||
ScopeID: scope.TemplateImportJobID,
|
||||
SourceScheme: database.ParameterSourceSchemeData,
|
||||
SourceValue: "secondnop",
|
||||
DestinationScheme: database.ParameterDestinationSchemeEnvironmentVariable,
|
||||
@@ -128,18 +128,18 @@ func TestCompute(t *testing.T) {
|
||||
require.Equal(t, value.SourceValue, computed[0].SourceValue)
|
||||
})
|
||||
|
||||
t.Run("ProjectOverridesProjectDefault", func(t *testing.T) {
|
||||
t.Run("TemplateOverridesTemplateDefault", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
scope := generateScope()
|
||||
parameterSchema := generateParameter(t, db, parameterOptions{
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
TemplateImportJobID: scope.TemplateImportJobID,
|
||||
})
|
||||
value, err := db.InsertParameterValue(context.Background(), database.InsertParameterValueParams{
|
||||
ID: uuid.New(),
|
||||
Name: parameterSchema.Name,
|
||||
Scope: database.ParameterScopeProject,
|
||||
ScopeID: scope.ProjectID.UUID,
|
||||
Scope: database.ParameterScopeTemplate,
|
||||
ScopeID: scope.TemplateID.UUID,
|
||||
SourceScheme: database.ParameterSourceSchemeData,
|
||||
SourceValue: "nop",
|
||||
DestinationScheme: database.ParameterDestinationSchemeEnvironmentVariable,
|
||||
@@ -153,12 +153,12 @@ func TestCompute(t *testing.T) {
|
||||
require.Equal(t, value.SourceValue, computed[0].SourceValue)
|
||||
})
|
||||
|
||||
t.Run("WorkspaceCannotOverwriteProjectDefault", func(t *testing.T) {
|
||||
t.Run("WorkspaceCannotOverwriteTemplateDefault", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
scope := generateScope()
|
||||
parameterSchema := generateParameter(t, db, parameterOptions{
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
TemplateImportJobID: scope.TemplateImportJobID,
|
||||
})
|
||||
|
||||
_, err := db.InsertParameterValue(context.Background(), database.InsertParameterValueParams{
|
||||
@@ -178,13 +178,13 @@ func TestCompute(t *testing.T) {
|
||||
require.Equal(t, true, computed[0].DefaultSourceValue)
|
||||
})
|
||||
|
||||
t.Run("WorkspaceOverwriteProjectDefault", func(t *testing.T) {
|
||||
t.Run("WorkspaceOverwriteTemplateDefault", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := databasefake.New()
|
||||
scope := generateScope()
|
||||
parameterSchema := generateParameter(t, db, parameterOptions{
|
||||
AllowOverrideSource: true,
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
TemplateImportJobID: scope.TemplateImportJobID,
|
||||
})
|
||||
_, err := db.InsertParameterValue(context.Background(), database.InsertParameterValueParams{
|
||||
ID: uuid.New(),
|
||||
@@ -208,7 +208,7 @@ func TestCompute(t *testing.T) {
|
||||
db := databasefake.New()
|
||||
scope := generateScope()
|
||||
_ = generateParameter(t, db, parameterOptions{
|
||||
ProjectImportJobID: scope.ProjectImportJobID,
|
||||
TemplateImportJobID: scope.TemplateImportJobID,
|
||||
DefaultDestinationScheme: database.ParameterDestinationSchemeProvisionerVariable,
|
||||
})
|
||||
computed, err := parameter.Compute(context.Background(), db, scope, ¶meter.ComputeOptions{
|
||||
|
||||
@@ -143,8 +143,8 @@ func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.Parameter
|
||||
switch chi.URLParam(r, "scope") {
|
||||
case string(codersdk.ParameterOrganization):
|
||||
scope = database.ParameterScopeOrganization
|
||||
case string(codersdk.ParameterProject):
|
||||
scope = database.ParameterScopeProject
|
||||
case string(codersdk.ParameterTemplate):
|
||||
scope = database.ParameterScopeTemplate
|
||||
case string(codersdk.ParameterUser):
|
||||
scope = database.ParameterScopeUser
|
||||
case string(codersdk.ParameterWorkspace):
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
package coderd
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/coderd/httpmw"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
// Returns a single project.
|
||||
func (api *api) project(rw http.ResponseWriter, r *http.Request) {
|
||||
project := httpmw.ProjectParam(r)
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByProjectIDs(r.Context(), []uuid.UUID{project.ID})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get workspace counts: %s", err.Error()),
|
||||
})
|
||||
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))
|
||||
}
|
||||
|
||||
func (api *api) deleteProject(rw http.ResponseWriter, r *http.Request) {
|
||||
project := httpmw.ProjectParam(r)
|
||||
|
||||
workspaces, err := api.Database.GetWorkspacesByProjectID(r.Context(), database.GetWorkspacesByProjectIDParams{
|
||||
ProjectID: project.ID,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get workspaces by project id: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if len(workspaces) > 0 {
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: "All workspaces must be deleted before a project can be removed.",
|
||||
})
|
||||
return
|
||||
}
|
||||
err = api.Database.UpdateProjectDeletedByID(r.Context(), database.UpdateProjectDeletedByIDParams{
|
||||
ID: project.ID,
|
||||
Deleted: true,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("update project deleted by id: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(rw, http.StatusOK, httpapi.Response{
|
||||
Message: "Project has been deleted!",
|
||||
})
|
||||
}
|
||||
|
||||
func (api *api) projectVersionsByProject(rw http.ResponseWriter, r *http.Request) {
|
||||
project := httpmw.ProjectParam(r)
|
||||
|
||||
versions, err := api.Database.GetProjectVersionsByProjectID(r.Context(), project.ID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
jobIDs := make([]uuid.UUID, 0, len(versions))
|
||||
for _, version := range versions {
|
||||
jobIDs = append(jobIDs, version.JobID)
|
||||
}
|
||||
jobs, err := api.Database.GetProvisionerJobsByIDs(r.Context(), jobIDs)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get jobs: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
jobByID := map[string]database.ProvisionerJob{}
|
||||
for _, job := range jobs {
|
||||
jobByID[job.ID.String()] = job
|
||||
}
|
||||
|
||||
apiVersion := make([]codersdk.ProjectVersion, 0)
|
||||
for _, version := range versions {
|
||||
job, exists := jobByID[version.JobID.String()]
|
||||
if !exists {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("job %q doesn't exist for version %q", version.JobID, version.ID),
|
||||
})
|
||||
return
|
||||
}
|
||||
apiVersion = append(apiVersion, convertProjectVersion(version, convertProvisionerJob(job)))
|
||||
}
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, apiVersion)
|
||||
}
|
||||
|
||||
func (api *api) projectVersionByName(rw http.ResponseWriter, r *http.Request) {
|
||||
project := httpmw.ProjectParam(r)
|
||||
projectVersionName := chi.URLParam(r, "projectversionname")
|
||||
projectVersion, err := api.Database.GetProjectVersionByProjectIDAndName(r.Context(), database.GetProjectVersionByProjectIDAndNameParams{
|
||||
ProjectID: uuid.NullUUID{
|
||||
UUID: project.ID,
|
||||
Valid: true,
|
||||
},
|
||||
Name: projectVersionName,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("no project version found by name %q", projectVersionName),
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version by name: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertProjectVersion(projectVersion, convertProvisionerJob(job)))
|
||||
}
|
||||
|
||||
func (api *api) patchActiveProjectVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
var req codersdk.UpdateActiveProjectVersion
|
||||
if !httpapi.Read(rw, r, &req) {
|
||||
return
|
||||
}
|
||||
project := httpmw.ProjectParam(r)
|
||||
version, err := api.Database.GetProjectVersionByID(r.Context(), req.ID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: "project version not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if version.ProjectID.UUID.String() != project.ID.String() {
|
||||
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
|
||||
Message: "The provided project version doesn't belong to the specified project.",
|
||||
})
|
||||
return
|
||||
}
|
||||
err = api.Database.UpdateProjectActiveVersionByID(r.Context(), database.UpdateProjectActiveVersionByIDParams{
|
||||
ID: project.ID,
|
||||
ActiveVersionID: req.ID,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("update active project version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(rw, http.StatusOK, httpapi.Response{
|
||||
Message: "Updated the active project version!",
|
||||
})
|
||||
}
|
||||
|
||||
func convertProjects(projects []database.Project, workspaceCounts []database.GetWorkspaceOwnerCountsByProjectIDsRow) []codersdk.Project {
|
||||
apiProjects := make([]codersdk.Project, 0, len(projects))
|
||||
for _, project := range projects {
|
||||
found := false
|
||||
for _, workspaceCount := range workspaceCounts {
|
||||
if workspaceCount.ProjectID.String() != project.ID.String() {
|
||||
continue
|
||||
}
|
||||
apiProjects = append(apiProjects, convertProject(project, uint32(workspaceCount.Count)))
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if !found {
|
||||
apiProjects = append(apiProjects, convertProject(project, uint32(0)))
|
||||
}
|
||||
}
|
||||
return apiProjects
|
||||
}
|
||||
|
||||
func convertProject(project database.Project, workspaceOwnerCount uint32) codersdk.Project {
|
||||
return codersdk.Project{
|
||||
ID: project.ID,
|
||||
CreatedAt: project.CreatedAt,
|
||||
UpdatedAt: project.UpdatedAt,
|
||||
OrganizationID: project.OrganizationID,
|
||||
Name: project.Name,
|
||||
Provisioner: project.Provisioner,
|
||||
ActiveVersionID: project.ActiveVersionID,
|
||||
WorkspaceOwnerCount: workspaceOwnerCount,
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func TestProject(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.Project(context.Background(), project.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDeleteProject(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("NoWorkspaces", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
err := client.DeleteProject(context.Background(), project.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Workspaces", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
err := client.DeleteProject(context.Background(), project.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectVersionsByProject(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
versions, err := client.ProjectVersionsByProject(context.Background(), project.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, versions, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectVersionByName(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotFound", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.ProjectVersionByName(context.Background(), project.ID, "nothing")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("Found", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.ProjectVersionByName(context.Background(), project.ID, version.Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPatchActiveProjectVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotFound", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
err := client.UpdateActiveProjectVersion(context.Background(), project.ID, codersdk.UpdateActiveProjectVersion{
|
||||
ID: uuid.New(),
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("DoesNotBelong", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
version = coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
err := client.UpdateActiveProjectVersion(context.Background(), project.ID, codersdk.UpdateActiveProjectVersion{
|
||||
ID: version.ID,
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("Found", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
err := client.UpdateActiveProjectVersion(context.Background(), project.ID, codersdk.UpdateActiveProjectVersion{
|
||||
ID: version.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
@@ -177,13 +177,13 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
|
||||
if err != nil {
|
||||
return nil, failJob(fmt.Sprintf("get workspace: %s", err))
|
||||
}
|
||||
projectVersion, err := server.Database.GetProjectVersionByID(ctx, workspaceBuild.ProjectVersionID)
|
||||
templateVersion, err := server.Database.GetTemplateVersionByID(ctx, workspaceBuild.TemplateVersionID)
|
||||
if err != nil {
|
||||
return nil, failJob(fmt.Sprintf("get project version: %s", err))
|
||||
return nil, failJob(fmt.Sprintf("get template version: %s", err))
|
||||
}
|
||||
project, err := server.Database.GetProjectByID(ctx, projectVersion.ProjectID.UUID)
|
||||
template, err := server.Database.GetTemplateByID(ctx, templateVersion.TemplateID.UUID)
|
||||
if err != nil {
|
||||
return nil, failJob(fmt.Sprintf("get project: %s", err))
|
||||
return nil, failJob(fmt.Sprintf("get template: %s", err))
|
||||
}
|
||||
owner, err := server.Database.GetUserByID(ctx, workspace.OwnerID)
|
||||
if err != nil {
|
||||
@@ -192,10 +192,10 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
|
||||
|
||||
// Compute parameters for the workspace to consume.
|
||||
parameters, err := parameter.Compute(ctx, server.Database, parameter.ComputeScope{
|
||||
ProjectImportJobID: projectVersion.JobID,
|
||||
OrganizationID: job.OrganizationID,
|
||||
ProjectID: uuid.NullUUID{
|
||||
UUID: project.ID,
|
||||
TemplateImportJobID: templateVersion.JobID,
|
||||
OrganizationID: job.OrganizationID,
|
||||
TemplateID: uuid.NullUUID{
|
||||
UUID: template.ID,
|
||||
Valid: true,
|
||||
},
|
||||
UserID: user.ID,
|
||||
@@ -235,9 +235,9 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
|
||||
},
|
||||
},
|
||||
}
|
||||
case database.ProvisionerJobTypeProjectVersionImport:
|
||||
protoJob.Type = &proto.AcquiredJob_ProjectImport_{
|
||||
ProjectImport: &proto.AcquiredJob_ProjectImport{
|
||||
case database.ProvisionerJobTypeTemplateVersionImport:
|
||||
protoJob.Type = &proto.AcquiredJob_TemplateImport_{
|
||||
TemplateImport: &proto.AcquiredJob_TemplateImport{
|
||||
Metadata: &sdkproto.Provision_Metadata{
|
||||
CoderUrl: server.AccessURL.String(),
|
||||
},
|
||||
@@ -250,7 +250,7 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
|
||||
if err != nil {
|
||||
return nil, failJob(fmt.Sprintf("get file by hash: %s", err))
|
||||
}
|
||||
protoJob.ProjectSourceArchive = file.Data
|
||||
protoJob.TemplateSourceArchive = file.Data
|
||||
default:
|
||||
return nil, failJob(fmt.Sprintf("unsupported storage method: %s", job.StorageMethod))
|
||||
}
|
||||
@@ -366,20 +366,20 @@ func (server *provisionerdServer) UpdateJob(ctx context.Context, request *proto.
|
||||
}
|
||||
}
|
||||
|
||||
var projectID uuid.NullUUID
|
||||
if job.Type == database.ProvisionerJobTypeProjectVersionImport {
|
||||
projectVersion, err := server.Database.GetProjectVersionByJobID(ctx, job.ID)
|
||||
var templateID uuid.NullUUID
|
||||
if job.Type == database.ProvisionerJobTypeTemplateVersionImport {
|
||||
templateVersion, err := server.Database.GetTemplateVersionByJobID(ctx, job.ID)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get project version by job id: %w", err)
|
||||
return nil, xerrors.Errorf("get template version by job id: %w", err)
|
||||
}
|
||||
projectID = projectVersion.ProjectID
|
||||
templateID = templateVersion.TemplateID
|
||||
}
|
||||
|
||||
parameters, err := parameter.Compute(ctx, server.Database, parameter.ComputeScope{
|
||||
ProjectImportJobID: job.ID,
|
||||
ProjectID: projectID,
|
||||
OrganizationID: job.OrganizationID,
|
||||
UserID: job.InitiatorID,
|
||||
TemplateImportJobID: job.ID,
|
||||
TemplateID: templateID,
|
||||
OrganizationID: job.OrganizationID,
|
||||
UserID: job.InitiatorID,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("compute parameters: %w", err)
|
||||
@@ -450,7 +450,7 @@ func (server *provisionerdServer) FailJob(ctx context.Context, failJob *proto.Fa
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("update workspace build state: %w", err)
|
||||
}
|
||||
case *proto.FailedJob_ProjectImport_:
|
||||
case *proto.FailedJob_TemplateImport_:
|
||||
}
|
||||
return &proto.Empty{}, nil
|
||||
}
|
||||
@@ -470,17 +470,17 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr
|
||||
}
|
||||
|
||||
switch jobType := completed.Type.(type) {
|
||||
case *proto.CompletedJob_ProjectImport_:
|
||||
case *proto.CompletedJob_TemplateImport_:
|
||||
for transition, resources := range map[database.WorkspaceTransition][]*sdkproto.Resource{
|
||||
database.WorkspaceTransitionStart: jobType.ProjectImport.StartResources,
|
||||
database.WorkspaceTransitionStop: jobType.ProjectImport.StopResources,
|
||||
database.WorkspaceTransitionStart: jobType.TemplateImport.StartResources,
|
||||
database.WorkspaceTransitionStop: jobType.TemplateImport.StopResources,
|
||||
} {
|
||||
addresses, err := provisionersdk.ResourceAddresses(resources)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("compute resource addresses: %w", err)
|
||||
}
|
||||
for index, resource := range resources {
|
||||
server.Logger.Info(ctx, "inserting project import job resource",
|
||||
server.Logger.Info(ctx, "inserting template import job resource",
|
||||
slog.F("job_id", job.ID.String()),
|
||||
slog.F("resource_name", resource.Name),
|
||||
slog.F("resource_type", resource.Type),
|
||||
|
||||
@@ -21,7 +21,7 @@ func TestProvisionerJobLogs(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -36,9 +36,9 @@ 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, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
before := time.Now().UTC()
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestProvisionerJobLogs(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -74,9 +74,9 @@ 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, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
before := database.Now()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancelFunc)
|
||||
@@ -95,7 +95,7 @@ func TestProvisionerJobLogs(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -110,9 +110,9 @@ 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, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
logs, err := client.WorkspaceBuildLogsBefore(context.Background(), workspace.LatestBuild.ID, time.Now())
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
package coderd
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/coderd/httpmw"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
// Returns a single template.
|
||||
func (api *api) template(rw http.ResponseWriter, r *http.Request) {
|
||||
template := httpmw.TemplateParam(r)
|
||||
workspaceCounts, err := api.Database.GetWorkspaceOwnerCountsByTemplateIDs(r.Context(), []uuid.UUID{template.ID})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get workspace counts: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
count := uint32(0)
|
||||
if len(workspaceCounts) > 0 {
|
||||
count = uint32(workspaceCounts[0].Count)
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertTemplate(template, count))
|
||||
}
|
||||
|
||||
func (api *api) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
|
||||
template := httpmw.TemplateParam(r)
|
||||
|
||||
workspaces, err := api.Database.GetWorkspacesByTemplateID(r.Context(), database.GetWorkspacesByTemplateIDParams{
|
||||
TemplateID: template.ID,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get workspaces by template id: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if len(workspaces) > 0 {
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: "All workspaces must be deleted before a template can be removed.",
|
||||
})
|
||||
return
|
||||
}
|
||||
err = api.Database.UpdateTemplateDeletedByID(r.Context(), database.UpdateTemplateDeletedByIDParams{
|
||||
ID: template.ID,
|
||||
Deleted: true,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("update template deleted by id: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(rw, http.StatusOK, httpapi.Response{
|
||||
Message: "Template has been deleted!",
|
||||
})
|
||||
}
|
||||
|
||||
func (api *api) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Request) {
|
||||
template := httpmw.TemplateParam(r)
|
||||
|
||||
versions, err := api.Database.GetTemplateVersionsByTemplateID(r.Context(), template.ID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get template version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
jobIDs := make([]uuid.UUID, 0, len(versions))
|
||||
for _, version := range versions {
|
||||
jobIDs = append(jobIDs, version.JobID)
|
||||
}
|
||||
jobs, err := api.Database.GetProvisionerJobsByIDs(r.Context(), jobIDs)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get jobs: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
jobByID := map[string]database.ProvisionerJob{}
|
||||
for _, job := range jobs {
|
||||
jobByID[job.ID.String()] = job
|
||||
}
|
||||
|
||||
apiVersion := make([]codersdk.TemplateVersion, 0)
|
||||
for _, version := range versions {
|
||||
job, exists := jobByID[version.JobID.String()]
|
||||
if !exists {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("job %q doesn't exist for version %q", version.JobID, version.ID),
|
||||
})
|
||||
return
|
||||
}
|
||||
apiVersion = append(apiVersion, convertTemplateVersion(version, convertProvisionerJob(job)))
|
||||
}
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, apiVersion)
|
||||
}
|
||||
|
||||
func (api *api) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
|
||||
template := httpmw.TemplateParam(r)
|
||||
templateVersionName := chi.URLParam(r, "templateversionname")
|
||||
templateVersion, err := api.Database.GetTemplateVersionByTemplateIDAndName(r.Context(), database.GetTemplateVersionByTemplateIDAndNameParams{
|
||||
TemplateID: uuid.NullUUID{
|
||||
UUID: template.ID,
|
||||
Valid: true,
|
||||
},
|
||||
Name: templateVersionName,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("no template version found by name %q", templateVersionName),
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get template version by name: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
|
||||
}
|
||||
|
||||
func (api *api) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
var req codersdk.UpdateActiveTemplateVersion
|
||||
if !httpapi.Read(rw, r, &req) {
|
||||
return
|
||||
}
|
||||
template := httpmw.TemplateParam(r)
|
||||
version, err := api.Database.GetTemplateVersionByID(r.Context(), req.ID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: "template version not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get template version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if version.TemplateID.UUID.String() != template.ID.String() {
|
||||
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
|
||||
Message: "The provided template version doesn't belong to the specified template.",
|
||||
})
|
||||
return
|
||||
}
|
||||
err = api.Database.UpdateTemplateActiveVersionByID(r.Context(), database.UpdateTemplateActiveVersionByIDParams{
|
||||
ID: template.ID,
|
||||
ActiveVersionID: req.ID,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("update active template version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(rw, http.StatusOK, httpapi.Response{
|
||||
Message: "Updated the active template version!",
|
||||
})
|
||||
}
|
||||
|
||||
func convertTemplates(templates []database.Template, workspaceCounts []database.GetWorkspaceOwnerCountsByTemplateIDsRow) []codersdk.Template {
|
||||
apiTemplates := make([]codersdk.Template, 0, len(templates))
|
||||
for _, template := range templates {
|
||||
found := false
|
||||
for _, workspaceCount := range workspaceCounts {
|
||||
if workspaceCount.TemplateID.String() != template.ID.String() {
|
||||
continue
|
||||
}
|
||||
apiTemplates = append(apiTemplates, convertTemplate(template, uint32(workspaceCount.Count)))
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if !found {
|
||||
apiTemplates = append(apiTemplates, convertTemplate(template, uint32(0)))
|
||||
}
|
||||
}
|
||||
return apiTemplates
|
||||
}
|
||||
|
||||
func convertTemplate(template database.Template, workspaceOwnerCount uint32) codersdk.Template {
|
||||
return codersdk.Template{
|
||||
ID: template.ID,
|
||||
CreatedAt: template.CreatedAt,
|
||||
UpdatedAt: template.UpdatedAt,
|
||||
OrganizationID: template.OrganizationID,
|
||||
Name: template.Name,
|
||||
Provisioner: template.Provisioner,
|
||||
ActiveVersionID: template.ActiveVersionID,
|
||||
WorkspaceOwnerCount: workspaceOwnerCount,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func TestTemplate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.Template(context.Background(), template.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDeleteTemplate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("NoWorkspaces", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
err := client.DeleteTemplate(context.Background(), template.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Workspaces", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
err := client.DeleteTemplate(context.Background(), template.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateVersionsByTemplate(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
versions, err := client.TemplateVersionsByTemplate(context.Background(), template.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, versions, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateVersionByName(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotFound", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.TemplateVersionByName(context.Background(), template.ID, "nothing")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("Found", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
_, err := client.TemplateVersionByName(context.Background(), template.ID, version.Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPatchActiveTemplateVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotFound", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
err := client.UpdateActiveTemplateVersion(context.Background(), template.ID, codersdk.UpdateActiveTemplateVersion{
|
||||
ID: uuid.New(),
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("DoesNotBelong", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
err := client.UpdateActiveTemplateVersion(context.Background(), template.ID, codersdk.UpdateActiveTemplateVersion{
|
||||
ID: version.ID,
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("Found", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
err := client.UpdateActiveTemplateVersion(context.Background(), template.ID, codersdk.UpdateActiveTemplateVersion{
|
||||
ID: version.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func (api *api) projectVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
projectVersion := httpmw.ProjectVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
func (api *api) templateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
@@ -25,12 +25,12 @@ func (api *api) projectVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertProjectVersion(projectVersion, convertProvisionerJob(job)))
|
||||
render.JSON(rw, r, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
|
||||
}
|
||||
|
||||
func (api *api) patchCancelProjectVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
projectVersion := httpmw.ProjectVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
func (api *api) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
@@ -67,9 +67,9 @@ func (api *api) patchCancelProjectVersion(rw http.ResponseWriter, r *http.Reques
|
||||
})
|
||||
}
|
||||
|
||||
func (api *api) projectVersionSchema(rw http.ResponseWriter, r *http.Request) {
|
||||
projectVersion := httpmw.ProjectVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
func (api *api) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
@@ -78,7 +78,7 @@ func (api *api) projectVersionSchema(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if !job.CompletedAt.Valid {
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: "Project version job hasn't completed!",
|
||||
Message: "Template version job hasn't completed!",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -99,10 +99,10 @@ func (api *api) projectVersionSchema(rw http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(rw, r, schemas)
|
||||
}
|
||||
|
||||
func (api *api) projectVersionParameters(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *api) templateVersionParameters(rw http.ResponseWriter, r *http.Request) {
|
||||
apiKey := httpmw.APIKey(r)
|
||||
projectVersion := httpmw.ProjectVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
@@ -116,9 +116,9 @@ func (api *api) projectVersionParameters(rw http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
values, err := parameter.Compute(r.Context(), api.Database, parameter.ComputeScope{
|
||||
ProjectImportJobID: job.ID,
|
||||
OrganizationID: job.OrganizationID,
|
||||
UserID: apiKey.UserID,
|
||||
TemplateImportJobID: job.ID,
|
||||
OrganizationID: job.OrganizationID,
|
||||
UserID: apiKey.UserID,
|
||||
}, ¶meter.ComputeOptions{
|
||||
// We *never* want to send the client secret parameter values.
|
||||
HideRedisplayValues: true,
|
||||
@@ -136,9 +136,9 @@ func (api *api) projectVersionParameters(rw http.ResponseWriter, r *http.Request
|
||||
render.JSON(rw, r, values)
|
||||
}
|
||||
|
||||
func (api *api) projectVersionResources(rw http.ResponseWriter, r *http.Request) {
|
||||
projectVersion := httpmw.ProjectVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
func (api *api) templateVersionResources(rw http.ResponseWriter, r *http.Request) {
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
@@ -148,9 +148,9 @@ func (api *api) projectVersionResources(rw http.ResponseWriter, r *http.Request)
|
||||
api.provisionerJobResources(rw, r, job)
|
||||
}
|
||||
|
||||
func (api *api) projectVersionLogs(rw http.ResponseWriter, r *http.Request) {
|
||||
projectVersion := httpmw.ProjectVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
func (api *api) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
@@ -160,13 +160,13 @@ func (api *api) projectVersionLogs(rw http.ResponseWriter, r *http.Request) {
|
||||
api.provisionerJobLogs(rw, r, job)
|
||||
}
|
||||
|
||||
func convertProjectVersion(version database.ProjectVersion, job codersdk.ProvisionerJob) codersdk.ProjectVersion {
|
||||
return codersdk.ProjectVersion{
|
||||
ID: version.ID,
|
||||
ProjectID: &version.ProjectID.UUID,
|
||||
CreatedAt: version.CreatedAt,
|
||||
UpdatedAt: version.UpdatedAt,
|
||||
Name: version.Name,
|
||||
Job: job,
|
||||
func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob) codersdk.TemplateVersion {
|
||||
return codersdk.TemplateVersion{
|
||||
ID: version.ID,
|
||||
TemplateID: &version.TemplateID.UUID,
|
||||
CreatedAt: version.CreatedAt,
|
||||
UpdatedAt: version.UpdatedAt,
|
||||
Name: version.Name,
|
||||
Job: job,
|
||||
}
|
||||
}
|
||||
@@ -15,28 +15,28 @@ import (
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
)
|
||||
|
||||
func TestProjectVersion(t *testing.T) {
|
||||
func TestTemplateVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.ProjectVersion(context.Background(), version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.TemplateVersion(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPatchCancelProjectVersion(t *testing.T) {
|
||||
func TestPatchCancelTemplateVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("AlreadyCompleted", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
err := client.CancelProjectVersion(context.Background(), version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
err := client.CancelTemplateVersion(context.Background(), version.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
@@ -46,7 +46,7 @@ func TestPatchCancelProjectVersion(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -56,14 +56,14 @@ func TestPatchCancelProjectVersion(t *testing.T) {
|
||||
})
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
version, err = client.ProjectVersion(context.Background(), version.ID)
|
||||
version, err = client.TemplateVersion(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
t.Logf("Status: %s", version.Job.Status)
|
||||
return version.Job.Status == codersdk.ProvisionerJobRunning
|
||||
}, 5*time.Second, 25*time.Millisecond)
|
||||
err := client.CancelProjectVersion(context.Background(), version.ID)
|
||||
err := client.CancelTemplateVersion(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
err = client.CancelProjectVersion(context.Background(), version.ID)
|
||||
err = client.CancelTemplateVersion(context.Background(), version.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
@@ -73,7 +73,7 @@ func TestPatchCancelProjectVersion(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -83,30 +83,30 @@ func TestPatchCancelProjectVersion(t *testing.T) {
|
||||
})
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
version, err = client.ProjectVersion(context.Background(), version.ID)
|
||||
version, err = client.TemplateVersion(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
t.Logf("Status: %s", version.Job.Status)
|
||||
return version.Job.Status == codersdk.ProvisionerJobRunning
|
||||
}, 5*time.Second, 25*time.Millisecond)
|
||||
err := client.CancelProjectVersion(context.Background(), version.ID)
|
||||
err := client.CancelTemplateVersion(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
version, err = client.ProjectVersion(context.Background(), version.ID)
|
||||
version, err = client.TemplateVersion(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
return version.Job.Status == codersdk.ProvisionerJobCanceled
|
||||
}, 5*time.Second, 25*time.Millisecond)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectVersionSchema(t *testing.T) {
|
||||
func TestTemplateVersionSchema(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("ListRunning", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.ProjectVersionSchema(context.Background(), version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.TemplateVersionSchema(context.Background(), version.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
@@ -116,7 +116,7 @@ func TestProjectVersionSchema(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: []*proto.Parse_Response{{
|
||||
Type: &proto.Parse_Response_Complete{
|
||||
Complete: &proto.Parse_Complete{
|
||||
@@ -131,22 +131,22 @@ func TestProjectVersionSchema(t *testing.T) {
|
||||
}},
|
||||
Provision: echo.ProvisionComplete,
|
||||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
schemas, err := client.ProjectVersionSchema(context.Background(), version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
schemas, err := client.TemplateVersionSchema(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, schemas)
|
||||
require.Len(t, schemas, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectVersionParameters(t *testing.T) {
|
||||
func TestTemplateVersionParameters(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("ListRunning", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.ProjectVersionParameters(context.Background(), version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.TemplateVersionParameters(context.Background(), version.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
@@ -156,7 +156,7 @@ func TestProjectVersionParameters(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: []*proto.Parse_Response{{
|
||||
Type: &proto.Parse_Response_Complete{
|
||||
Complete: &proto.Parse_Complete{
|
||||
@@ -176,8 +176,8 @@ func TestProjectVersionParameters(t *testing.T) {
|
||||
}},
|
||||
Provision: echo.ProvisionComplete,
|
||||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
params, err := client.ProjectVersionParameters(context.Background(), version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
params, err := client.TemplateVersionParameters(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, params)
|
||||
require.Len(t, params, 1)
|
||||
@@ -185,14 +185,14 @@ func TestProjectVersionParameters(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectVersionResources(t *testing.T) {
|
||||
func TestTemplateVersionResources(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("ListRunning", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.ProjectVersionResources(context.Background(), version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_, err := client.TemplateVersionResources(context.Background(), version.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode())
|
||||
@@ -202,7 +202,7 @@ func TestProjectVersionResources(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
@@ -222,8 +222,8 @@ func TestProjectVersionResources(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
resources, err := client.ProjectVersionResources(context.Background(), version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
resources, err := client.TemplateVersionResources(context.Background(), version.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resources)
|
||||
require.Len(t, resources, 4)
|
||||
@@ -233,13 +233,13 @@ func TestProjectVersionResources(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestProjectVersionLogs(t *testing.T) {
|
||||
func TestTemplateVersionLogs(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
before := time.Now()
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionDryRun: echo.ProvisionComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
@@ -271,7 +271,7 @@ func TestProjectVersionLogs(t *testing.T) {
|
||||
})
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancelFunc)
|
||||
logs, err := client.ProjectVersionLogsAfter(ctx, version.ID, before)
|
||||
logs, err := client.TemplateVersionLogsAfter(ctx, version.ID, before)
|
||||
require.NoError(t, err)
|
||||
for {
|
||||
_, ok := <-logs
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
|
||||
// Compare checks the equality of passwords from a hashed pbkdf2 string.
|
||||
// This uses pbkdf2 to ensure FIPS 140-2 compliance. See:
|
||||
// https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp2261.pdf
|
||||
// https://csrc.nist.gov/csrc/media/templates/cryptographic-module-validation-program/documents/security-policies/140sp2261.pdf
|
||||
func Compare(hashed string, password string) (bool, error) {
|
||||
if len(hashed) < hashLength {
|
||||
return false, xerrors.Errorf("hash too short: %d", len(hashed))
|
||||
|
||||
+52
-52
@@ -529,12 +529,12 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
apiKey := httpmw.APIKey(r)
|
||||
project, err := api.Database.GetProjectByID(r.Context(), createWorkspace.ProjectID)
|
||||
template, err := api.Database.GetTemplateByID(r.Context(), createWorkspace.TemplateID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: fmt.Sprintf("project %q doesn't exist", createWorkspace.ProjectID.String()),
|
||||
Message: fmt.Sprintf("template %q doesn't exist", createWorkspace.TemplateID.String()),
|
||||
Errors: []httpapi.Error{{
|
||||
Field: "project_id",
|
||||
Field: "template_id",
|
||||
Code: "not_found",
|
||||
}},
|
||||
})
|
||||
@@ -542,17 +542,17 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project: %s", err),
|
||||
Message: fmt.Sprintf("get template: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
_, err = api.Database.GetOrganizationMemberByUserID(r.Context(), database.GetOrganizationMemberByUserIDParams{
|
||||
OrganizationID: project.OrganizationID,
|
||||
OrganizationID: template.OrganizationID,
|
||||
UserID: apiKey.UserID,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
|
||||
Message: "you aren't allowed to access projects in that organization",
|
||||
Message: "you aren't allowed to access templates in that organization",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -569,16 +569,16 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
if err == nil {
|
||||
// If the workspace already exists, don't allow creation.
|
||||
project, err := api.Database.GetProjectByID(r.Context(), workspace.ProjectID)
|
||||
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("find project for conflicting workspace name %q: %s", createWorkspace.Name, err),
|
||||
Message: fmt.Sprintf("find template for conflicting workspace name %q: %s", createWorkspace.Name, err),
|
||||
})
|
||||
return
|
||||
}
|
||||
// The project is fetched for clarity to the user on where the conflicting name may be.
|
||||
// The template is fetched for clarity to the user on where the conflicting name may be.
|
||||
httpapi.Write(rw, http.StatusConflict, httpapi.Response{
|
||||
Message: fmt.Sprintf("workspace %q already exists in the %q project", createWorkspace.Name, project.Name),
|
||||
Message: fmt.Sprintf("workspace %q already exists in the %q template", createWorkspace.Name, template.Name),
|
||||
Errors: []httpapi.Error{{
|
||||
Field: "name",
|
||||
Code: "exists",
|
||||
@@ -593,35 +593,35 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
projectVersion, err := api.Database.GetProjectVersionByID(r.Context(), project.ActiveVersionID)
|
||||
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), template.ActiveVersionID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version: %s", err),
|
||||
Message: fmt.Sprintf("get template version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
projectVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version job: %s", err),
|
||||
Message: fmt.Sprintf("get template version job: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
projectVersionJobStatus := convertProvisionerJob(projectVersionJob).Status
|
||||
switch projectVersionJobStatus {
|
||||
templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status
|
||||
switch templateVersionJobStatus {
|
||||
case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning:
|
||||
httpapi.Write(rw, http.StatusNotAcceptable, httpapi.Response{
|
||||
Message: fmt.Sprintf("The provided project version is %s. Wait for it to complete importing!", projectVersionJobStatus),
|
||||
Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus),
|
||||
})
|
||||
return
|
||||
case codersdk.ProvisionerJobFailed:
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: fmt.Sprintf("The provided project version %q has failed to import. You cannot create workspaces using it!", projectVersion.Name),
|
||||
Message: fmt.Sprintf("The provided template version %q has failed to import. You cannot create workspaces using it!", templateVersion.Name),
|
||||
})
|
||||
return
|
||||
case codersdk.ProvisionerJobCanceled:
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: "The provided project version was canceled during import. You cannot create workspaces using it!",
|
||||
Message: "The provided template version was canceled during import. You cannot create workspaces using it!",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -632,12 +632,12 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
workspaceBuildID := uuid.New()
|
||||
// Workspaces are created without any versions.
|
||||
workspace, err = db.InsertWorkspace(r.Context(), database.InsertWorkspaceParams{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
OwnerID: apiKey.UserID,
|
||||
ProjectID: project.ID,
|
||||
Name: createWorkspace.Name,
|
||||
ID: uuid.New(),
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
OwnerID: apiKey.UserID,
|
||||
TemplateID: template.ID,
|
||||
Name: createWorkspace.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert workspace: %w", err)
|
||||
@@ -670,26 +670,26 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
InitiatorID: apiKey.UserID,
|
||||
OrganizationID: project.OrganizationID,
|
||||
Provisioner: project.Provisioner,
|
||||
OrganizationID: template.OrganizationID,
|
||||
Provisioner: template.Provisioner,
|
||||
Type: database.ProvisionerJobTypeWorkspaceBuild,
|
||||
StorageMethod: projectVersionJob.StorageMethod,
|
||||
StorageSource: projectVersionJob.StorageSource,
|
||||
StorageMethod: templateVersionJob.StorageMethod,
|
||||
StorageSource: templateVersionJob.StorageSource,
|
||||
Input: input,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert provisioner job: %w", err)
|
||||
}
|
||||
workspaceBuild, err = db.InsertWorkspaceBuild(r.Context(), database.InsertWorkspaceBuildParams{
|
||||
ID: workspaceBuildID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
WorkspaceID: workspace.ID,
|
||||
ProjectVersionID: projectVersion.ID,
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
InitiatorID: apiKey.UserID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
JobID: provisionerJob.ID,
|
||||
ID: workspaceBuildID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
WorkspaceID: workspace.ID,
|
||||
TemplateVersionID: templateVersion.ID,
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
InitiatorID: apiKey.UserID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
JobID: provisionerJob.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert workspace build: %w", err)
|
||||
@@ -705,7 +705,7 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
render.Status(r, http.StatusCreated)
|
||||
render.JSON(rw, r, convertWorkspace(workspace,
|
||||
convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(projectVersionJob)), project))
|
||||
convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(templateVersionJob)), template))
|
||||
}
|
||||
|
||||
func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -723,10 +723,10 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
workspaceIDs := make([]uuid.UUID, 0, len(workspaces))
|
||||
projectIDs := make([]uuid.UUID, 0, len(workspaces))
|
||||
templateIDs := make([]uuid.UUID, 0, len(workspaces))
|
||||
for _, workspace := range workspaces {
|
||||
workspaceIDs = append(workspaceIDs, workspace.ID)
|
||||
projectIDs = append(projectIDs, workspace.ProjectID)
|
||||
templateIDs = append(templateIDs, workspace.TemplateID)
|
||||
}
|
||||
workspaceBuilds, err := api.Database.GetWorkspaceBuildsByWorkspaceIDsWithoutAfter(r.Context(), workspaceIDs)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
@@ -738,13 +738,13 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
return
|
||||
}
|
||||
projects, err := api.Database.GetProjectsByIDs(r.Context(), projectIDs)
|
||||
templates, err := api.Database.GetTemplatesByIDs(r.Context(), templateIDs)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get projects: %s", err),
|
||||
Message: fmt.Sprintf("get templates: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -767,9 +767,9 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
for _, workspaceBuild := range workspaceBuilds {
|
||||
buildByWorkspaceID[workspaceBuild.WorkspaceID] = workspaceBuild
|
||||
}
|
||||
projectByID := map[uuid.UUID]database.Project{}
|
||||
for _, project := range projects {
|
||||
projectByID[project.ID] = project
|
||||
templateByID := map[uuid.UUID]database.Template{}
|
||||
for _, template := range templates {
|
||||
templateByID[template.ID] = template
|
||||
}
|
||||
jobByID := map[uuid.UUID]database.ProvisionerJob{}
|
||||
for _, job := range jobs {
|
||||
@@ -784,10 +784,10 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
return
|
||||
}
|
||||
project, exists := projectByID[workspace.ProjectID]
|
||||
template, exists := templateByID[workspace.TemplateID]
|
||||
if !exists {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("project not found for workspace %q", workspace.Name),
|
||||
Message: fmt.Sprintf("template not found for workspace %q", workspace.Name),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -799,7 +799,7 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
apiWorkspaces = append(apiWorkspaces,
|
||||
convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), project))
|
||||
convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
|
||||
}
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, apiWorkspaces)
|
||||
@@ -838,17 +838,17 @@ func (api *api) workspaceByUserAndName(rw http.ResponseWriter, r *http.Request)
|
||||
})
|
||||
return
|
||||
}
|
||||
project, err := api.Database.GetProjectByID(r.Context(), workspace.ProjectID)
|
||||
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project: %s", err),
|
||||
Message: fmt.Sprintf("get template: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(rw, r, convertWorkspace(workspace,
|
||||
convertWorkspaceBuild(build, convertProvisionerJob(job)), project))
|
||||
convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
|
||||
}
|
||||
|
||||
// Generates a new ID and secret for an API key.
|
||||
|
||||
+26
-26
@@ -310,13 +310,13 @@ func TestPostAPIKey(t *testing.T) {
|
||||
|
||||
func TestPostWorkspacesByUser(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("InvalidProject", func(t *testing.T) {
|
||||
t.Run("InvalidTemplate", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
_, err := client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: uuid.New(),
|
||||
Name: "workspace",
|
||||
TemplateID: uuid.New(),
|
||||
Name: "workspace",
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiErr *codersdk.Error
|
||||
@@ -324,7 +324,7 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
||||
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("NoProjectAccess", func(t *testing.T) {
|
||||
t.Run("NoTemplateAccess", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
@@ -334,12 +334,12 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
||||
Name: "another",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
version := coderdtest.CreateProjectVersion(t, other, org.ID, nil)
|
||||
project := coderdtest.CreateProject(t, other, org.ID, version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, other, org.ID, nil)
|
||||
template := coderdtest.CreateTemplate(t, other, org.ID, version.ID)
|
||||
|
||||
_, err = client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: "workspace",
|
||||
TemplateID: template.ID,
|
||||
Name: "workspace",
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiErr *codersdk.Error
|
||||
@@ -352,13 +352,13 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: workspace.Name,
|
||||
TemplateID: template.ID,
|
||||
Name: workspace.Name,
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiErr *codersdk.Error
|
||||
@@ -371,10 +371,10 @@ func TestPostWorkspacesByUser(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
_ = coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -392,10 +392,10 @@ func TestWorkspacesByUser(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
_ = coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
workspaces, err := client.WorkspacesByUser(context.Background(), codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspaces, 1)
|
||||
@@ -418,10 +418,10 @@ func TestWorkspaceByUserAndName(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.WorkspaceByName(context.Background(), codersdk.Me, workspace.Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
+11
-11
@@ -92,17 +92,17 @@ func (api *api) workspaceBuildLogs(rw http.ResponseWriter, r *http.Request) {
|
||||
func convertWorkspaceBuild(workspaceBuild database.WorkspaceBuild, job codersdk.ProvisionerJob) codersdk.WorkspaceBuild {
|
||||
//nolint:unconvert
|
||||
return codersdk.WorkspaceBuild{
|
||||
ID: workspaceBuild.ID,
|
||||
CreatedAt: workspaceBuild.CreatedAt,
|
||||
UpdatedAt: workspaceBuild.UpdatedAt,
|
||||
WorkspaceID: workspaceBuild.WorkspaceID,
|
||||
ProjectVersionID: workspaceBuild.ProjectVersionID,
|
||||
BeforeID: workspaceBuild.BeforeID.UUID,
|
||||
AfterID: workspaceBuild.AfterID.UUID,
|
||||
Name: workspaceBuild.Name,
|
||||
Transition: workspaceBuild.Transition,
|
||||
InitiatorID: workspaceBuild.InitiatorID,
|
||||
Job: job,
|
||||
ID: workspaceBuild.ID,
|
||||
CreatedAt: workspaceBuild.CreatedAt,
|
||||
UpdatedAt: workspaceBuild.UpdatedAt,
|
||||
WorkspaceID: workspaceBuild.WorkspaceID,
|
||||
TemplateVersionID: workspaceBuild.TemplateVersionID,
|
||||
BeforeID: workspaceBuild.BeforeID.UUID,
|
||||
AfterID: workspaceBuild.AfterID.UUID,
|
||||
Name: workspaceBuild.Name,
|
||||
Transition: workspaceBuild.Transition,
|
||||
InitiatorID: workspaceBuild.InitiatorID,
|
||||
Job: job,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ func TestWorkspaceBuild(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.WorkspaceBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -41,9 +41,9 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) {
|
||||
}},
|
||||
ProvisionDryRun: echo.ProvisionComplete,
|
||||
})
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
var build codersdk.WorkspaceBuild
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
@@ -68,11 +68,11 @@ func TestWorkspaceBuildResources(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
closeDaemon := coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
closeDaemon.Close()
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
@@ -83,7 +83,7 @@ func TestWorkspaceBuildResources(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
@@ -103,9 +103,9 @@ 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, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
@@ -123,7 +123,7 @@ func TestWorkspaceBuildLogs(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
before := time.Now()
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Log{
|
||||
@@ -150,9 +150,9 @@ 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, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancelFunc)
|
||||
logs, err := client.WorkspaceBuildLogsAfter(ctx, workspace.LatestBuild.ID, before)
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestPostWorkspaceAuthAWSInstanceIdentity(t *testing.T) {
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
@@ -42,9 +42,9 @@ 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, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
client.HTTPClient = metadataClient
|
||||
@@ -90,7 +90,7 @@ func TestPostWorkspaceAuthGoogleInstanceIdentity(t *testing.T) {
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
@@ -108,9 +108,9 @@ 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, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
_, err := client.AuthWorkspaceGoogleInstanceIdentity(context.Background(), "", metadata)
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestWorkspaceResource(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
@@ -42,9 +42,9 @@ 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, codersdk.Me, project.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
@@ -59,7 +59,7 @@ func TestWorkspaceAgentListen(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
daemonCloser := coderdtest.NewProvisionerDaemon(t, client)
|
||||
authToken := uuid.NewString()
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionDryRun: echo.ProvisionComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
@@ -79,9 +79,9 @@ 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, codersdk.Me, project.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
daemonCloser.Close()
|
||||
|
||||
|
||||
+42
-42
@@ -37,14 +37,14 @@ func (api *api) workspace(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
return
|
||||
}
|
||||
project, err := api.Database.GetProjectByID(r.Context(), workspace.ProjectID)
|
||||
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project: %s", err),
|
||||
Message: fmt.Sprintf("get template: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
render.JSON(rw, r, convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), project))
|
||||
render.JSON(rw, r, convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
|
||||
}
|
||||
|
||||
func (api *api) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
||||
@@ -102,7 +102,7 @@ func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
||||
if !httpapi.Read(rw, r, &createBuild) {
|
||||
return
|
||||
}
|
||||
if createBuild.ProjectVersionID == uuid.Nil {
|
||||
if createBuild.TemplateVersionID == uuid.Nil {
|
||||
latestBuild, err := api.Database.GetWorkspaceBuildByWorkspaceIDWithoutAfter(r.Context(), workspace.ID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
@@ -110,14 +110,14 @@ func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
return
|
||||
}
|
||||
createBuild.ProjectVersionID = latestBuild.ProjectVersionID
|
||||
createBuild.TemplateVersionID = latestBuild.TemplateVersionID
|
||||
}
|
||||
projectVersion, err := api.Database.GetProjectVersionByID(r.Context(), createBuild.ProjectVersionID)
|
||||
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), createBuild.TemplateVersionID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "project version not found",
|
||||
Message: "template version not found",
|
||||
Errors: []httpapi.Error{{
|
||||
Field: "project_version_id",
|
||||
Field: "template_version_id",
|
||||
Code: "exists",
|
||||
}},
|
||||
})
|
||||
@@ -125,40 +125,40 @@ func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project version: %s", err),
|
||||
Message: fmt.Sprintf("get template version: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
projectVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), projectVersion.JobID)
|
||||
templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get provisioner job: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
projectVersionJobStatus := convertProvisionerJob(projectVersionJob).Status
|
||||
switch projectVersionJobStatus {
|
||||
templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status
|
||||
switch templateVersionJobStatus {
|
||||
case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning:
|
||||
httpapi.Write(rw, http.StatusNotAcceptable, httpapi.Response{
|
||||
Message: fmt.Sprintf("The provided project version is %s. Wait for it to complete importing!", projectVersionJobStatus),
|
||||
Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus),
|
||||
})
|
||||
return
|
||||
case codersdk.ProvisionerJobFailed:
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: fmt.Sprintf("The provided project version %q has failed to import: %q. You cannot build workspaces with it!", projectVersion.Name, projectVersionJob.Error.String),
|
||||
Message: fmt.Sprintf("The provided template version %q has failed to import: %q. You cannot build workspaces with it!", templateVersion.Name, templateVersionJob.Error.String),
|
||||
})
|
||||
return
|
||||
case codersdk.ProvisionerJobCanceled:
|
||||
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{
|
||||
Message: "The provided project version was canceled during import. You cannot builds workspaces with it!",
|
||||
Message: "The provided template version was canceled during import. You cannot builds workspaces with it!",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
project, err := api.Database.GetProjectByID(r.Context(), projectVersion.ProjectID.UUID)
|
||||
template, err := api.Database.GetTemplateByID(r.Context(), templateVersion.TemplateID.UUID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get project: %s", err),
|
||||
Message: fmt.Sprintf("get template: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -203,28 +203,28 @@ func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
InitiatorID: apiKey.UserID,
|
||||
OrganizationID: project.OrganizationID,
|
||||
Provisioner: project.Provisioner,
|
||||
OrganizationID: template.OrganizationID,
|
||||
Provisioner: template.Provisioner,
|
||||
Type: database.ProvisionerJobTypeWorkspaceBuild,
|
||||
StorageMethod: projectVersionJob.StorageMethod,
|
||||
StorageSource: projectVersionJob.StorageSource,
|
||||
StorageMethod: templateVersionJob.StorageMethod,
|
||||
StorageSource: templateVersionJob.StorageSource,
|
||||
Input: input,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert provisioner job: %w", err)
|
||||
}
|
||||
workspaceBuild, err = db.InsertWorkspaceBuild(r.Context(), database.InsertWorkspaceBuildParams{
|
||||
ID: workspaceBuildID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
WorkspaceID: workspace.ID,
|
||||
ProjectVersionID: projectVersion.ID,
|
||||
BeforeID: priorHistoryID,
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
ProvisionerState: priorHistory.ProvisionerState,
|
||||
InitiatorID: apiKey.UserID,
|
||||
Transition: createBuild.Transition,
|
||||
JobID: provisionerJob.ID,
|
||||
ID: workspaceBuildID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
WorkspaceID: workspace.ID,
|
||||
TemplateVersionID: templateVersion.ID,
|
||||
BeforeID: priorHistoryID,
|
||||
Name: namesgenerator.GetRandomName(1),
|
||||
ProvisionerState: priorHistory.ProvisionerState,
|
||||
InitiatorID: apiKey.UserID,
|
||||
Transition: createBuild.Transition,
|
||||
JobID: provisionerJob.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert workspace build: %w", err)
|
||||
@@ -290,16 +290,16 @@ func (api *api) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(rw, r, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(job)))
|
||||
}
|
||||
|
||||
func convertWorkspace(workspace database.Workspace, workspaceBuild codersdk.WorkspaceBuild, project database.Project) codersdk.Workspace {
|
||||
func convertWorkspace(workspace database.Workspace, workspaceBuild codersdk.WorkspaceBuild, template database.Template) codersdk.Workspace {
|
||||
return codersdk.Workspace{
|
||||
ID: workspace.ID,
|
||||
CreatedAt: workspace.CreatedAt,
|
||||
UpdatedAt: workspace.UpdatedAt,
|
||||
OwnerID: workspace.OwnerID,
|
||||
ProjectID: workspace.ProjectID,
|
||||
LatestBuild: workspaceBuild,
|
||||
ProjectName: project.Name,
|
||||
Outdated: workspaceBuild.ProjectVersionID.String() != project.ActiveVersionID.String(),
|
||||
Name: workspace.Name,
|
||||
ID: workspace.ID,
|
||||
CreatedAt: workspace.CreatedAt,
|
||||
UpdatedAt: workspace.UpdatedAt,
|
||||
OwnerID: workspace.OwnerID,
|
||||
TemplateID: workspace.TemplateID,
|
||||
LatestBuild: workspaceBuild,
|
||||
TemplateName: template.Name,
|
||||
Outdated: workspaceBuild.TemplateVersionID.String() != template.ActiveVersionID.String(),
|
||||
Name: workspace.Name,
|
||||
}
|
||||
}
|
||||
|
||||
+45
-45
@@ -20,10 +20,10 @@ func TestWorkspace(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.Workspace(context.Background(), workspace.ID)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -35,10 +35,10 @@ func TestWorkspaceBuilds(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.WorkspaceBuilds(context.Background(), workspace.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
@@ -46,18 +46,18 @@ func TestWorkspaceBuilds(t *testing.T) {
|
||||
|
||||
func TestPostWorkspaceBuild(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NoProjectVersion", func(t *testing.T) {
|
||||
t.Run("NoTemplateVersion", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
ProjectVersionID: uuid.New(),
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
TemplateVersionID: uuid.New(),
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiErr *codersdk.Error
|
||||
@@ -65,19 +65,19 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
||||
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("ProjectVersionFailedImport", func(t *testing.T) {
|
||||
t.Run("TemplateVersionFailedImport", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Provision: []*proto.Provision_Response{{}},
|
||||
})
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
_, err := client.CreateWorkspace(context.Background(), codersdk.Me, codersdk.CreateWorkspaceRequest{
|
||||
ProjectID: project.ID,
|
||||
Name: "workspace",
|
||||
TemplateID: template.ID,
|
||||
Name: "workspace",
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
@@ -89,15 +89,15 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
closeDaemon := coderdtest.NewProvisionerDaemon(t, client)
|
||||
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
|
||||
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
// Close here so workspace build doesn't process!
|
||||
closeDaemon.Close()
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, project.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
ProjectVersionID: project.ActiveVersionID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiErr *codersdk.Error
|
||||
@@ -110,14 +110,14 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
build, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
ProjectVersionID: project.ActiveVersionID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, workspace.LatestBuild.ID.String(), build.BeforeID.String())
|
||||
@@ -132,10 +132,10 @@ func TestPostWorkspaceBuild(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
build, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
Transition: database.WorkspaceTransitionDelete,
|
||||
@@ -157,10 +157,10 @@ func TestWorkspaceBuildByName(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
_, err := client.WorkspaceBuildByName(context.Background(), workspace.ID, "something")
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
@@ -172,10 +172,10 @@ func TestWorkspaceBuildByName(t *testing.T) {
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
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, codersdk.Me, project.ID)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
|
||||
build, err := client.WorkspaceBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
_, err = client.WorkspaceBuildByName(context.Background(), workspace.ID, build.Name)
|
||||
|
||||
Reference in New Issue
Block a user